Initial import

This commit is contained in:
Doug Macintosh
2026-01-04 10:55:36 -05:00
commit a59a047cd1
54 changed files with 107364 additions and 0 deletions

484
.gitignore vendored Normal file
View File

@@ -0,0 +1,484 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from `dotnet new gitignore`
# dotenv files
.env
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET
project.lock.json
project.fragment.lock.json
artifacts/
# Tye
.tye/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml
.idea
##
## Visual studio for Mac
##
# globs
Makefile.in
*.userprefs
*.usertasks
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.tar.gz
tarballs/
test-results/
# Mac bundle stuff
*.dmg
*.app
# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# Vim temporary swap files
*.swp

292
Arguments.cs Executable file
View File

@@ -0,0 +1,292 @@
/*
* Created by SharpDevelop.
* User: User
* Date: 1/19/2012
* Time: 6:41 PM
Example Usage
There are two ways you can start using this class, I have created a SplitCommandLine function which ignores escaped quotes, this is needed for path support, the trailing \ on the path causes the quote to be taken literally.
Using SplitCommandLine:
var commandLine = Environment.CommandLine;
var splitCommandLine = Arguments.SplitCommandLine(commandLine);
var arguments = new Arguments(splitCommandLine);
Letting windows do it:
static int Main(string[] args)
{
_args = new Arguments(args);
}
Example Arguments
Argument: flag
Usage: args.IsTrue("flag");
Result: true
Argument: arg:MyValue
Usage: args.Single("arg");
Result: MyValue
Argument: arg "My Value"
Usage: args.Single("arg");
Result: My Value
Argument: /arg=Value /arg=Value2
Usage: args["arg"]
Result: new string[] {"Value", "Value2"}
Argument: /arg="Value,Value2"
Usage: args["arg"]
Result: new string[] {"Value", "Value2"}
As you can see it is very flexible, it support [/]arg[:=]value and with the list support it makes it really useful and adaptable.
*/
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
//using System.Collections.Specialized;
using System.Text;
using System.Text.RegularExpressions;
namespace bdf
{
/// <summary>
/// Arguments class
/// Example Arguments
/// </summary>
public class Arguments
{
/// <summary>
/// Splits the command line. When main(string[] args) is used escaped quotes (ie a path "c:\folder\")
/// Will consume all the following command line arguments as the one argument.
/// This function ignores escaped quotes making handling paths much easier.
/// </summary>
/// <param name="commandLine">The command line.</param>
/// <returns></returns>
public static string[] SplitCommandLine(string commandLine)
{
var translatedArguments = new StringBuilder(commandLine);
var escaped = false;
for (var i = 0; i < translatedArguments.Length; i++)
{
if (translatedArguments[i] == '"')
{
escaped = !escaped;
}
if (translatedArguments[i] == ' ' && !escaped)
{
translatedArguments[i] = '\n';
}
}
var toReturn = translatedArguments.ToString().Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
for (var i = 0; i < toReturn.Length; i++)
{
toReturn[i] = RemoveMatchingQuotes(toReturn[i]);
}
return toReturn;
}
public static string RemoveMatchingQuotes(string stringToTrim)
{
var firstQuoteIndex = stringToTrim.IndexOf('"');
var lastQuoteIndex = stringToTrim.LastIndexOf('"');
while (firstQuoteIndex != lastQuoteIndex)
{
stringToTrim = stringToTrim.Remove(firstQuoteIndex, 1);
stringToTrim = stringToTrim.Remove(lastQuoteIndex - 1, 1); //-1 because we've shifted the indicies left by one
firstQuoteIndex = stringToTrim.IndexOf('"');
lastQuoteIndex = stringToTrim.LastIndexOf('"');
}
return stringToTrim;
}
private readonly Dictionary<string, Collection<string>> _parameters;
private string _waitingParameter;
public Arguments(IEnumerable<string> arguments) : this(arguments, false)
{
}
public Arguments(IEnumerable<string> arguments, bool ignoreCase)
{
//_parameters = new Dictionary<string, Collection<string>>();
Regex argumentSplitter;
if (ignoreCase)
{
//_parameters = new Dictionary<string, Collection<string>>(StringComparer.OrdinalIgnoreCase);
argumentSplitter = new Regex(@"^-{1,2}|^/|=", RegexOptions.Compiled);
_parameters = new Dictionary<string, Collection<string>>(StringComparer.Ordinal);
}
else
{
//_parameters = new Dictionary<string, Collection<string>>();
//Regex argumentSplitter = new Regex(@"^-{1}|^/", RegexOptions.IgnoreCase | RegexOptions.Compiled);
argumentSplitter = new Regex(@"^-{1,2}|^/|=", RegexOptions.IgnoreCase | RegexOptions.Compiled);
_parameters = new Dictionary<string, Collection<string>>(StringComparer.InvariantCultureIgnoreCase);
}
string[] parts;
//Splits on beginning of arguments ( - and -- and / )
//And on assignment operators ( = and : )
//Regex argumentSplitter = new Regex(@"^-{1,2}|^/|=|:",RegexOptions.IgnoreCase | RegexOptions.Compiled);
foreach (string argument in arguments)
{
parts = argumentSplitter.Split(argument, 3);
switch (parts.Length)
{
case 1:
AddValueToWaitingArgument(parts[0]);
break;
case 2:
AddWaitingArgumentAsFlag();
//Because of the split index 0 will be a empty string
_waitingParameter = parts[1];
break;
case 3:
AddWaitingArgumentAsFlag();
//Because of the split index 0 will be a empty string
string valuesWithoutQuotes = RemoveMatchingQuotes(parts[2]);
AddListValues(parts[1], valuesWithoutQuotes.Split(','));
break;
}
}
AddWaitingArgumentAsFlag();
}
private void AddListValues(string argument, IEnumerable<string> values)
{
foreach (var listValue in values)
{
Add(argument, listValue);
}
}
private void AddWaitingArgumentAsFlag()
{
if (_waitingParameter == null) return;
AddSingle(_waitingParameter, "true");
_waitingParameter = null;
}
private void AddValueToWaitingArgument(string value)
{
if (_waitingParameter == null) return;
value = RemoveMatchingQuotes(value);
Add(_waitingParameter, value);
_waitingParameter = null;
}
/// <summary>
/// Gets the count.
/// </summary>
/// <value>The count.</value>
public int Count
{
get
{
return _parameters.Count;
}
}
/// <summary>
/// Adds the specified argument.
/// </summary>
/// <param name="argument">The argument.</param>
/// <param name="value">The value.</param>
public void Add(string argument, string value)
{
if (!_parameters.ContainsKey(argument))
_parameters.Add(argument, new Collection<string>());
_parameters[argument].Add(value);
}
public void AddSingle(string argument, string value)
{
if (!_parameters.ContainsKey(argument))
_parameters.Add(argument, new Collection<string>());
else
throw new ArgumentException(string.Format("Argument {0} has already been defined", argument));
_parameters[argument].Add(value);
}
public void Remove(string argument)
{
if (_parameters.ContainsKey(argument))
_parameters.Remove(argument);
}
/// <summary>
/// Determines whether the specified argument is true.
/// </summary>
/// <param name="argument">The argument.</param>
/// <returns>
/// <c>true</c> if the specified argument is true; otherwise, <c>false</c>.
/// </returns>
public bool IsTrue(string argument)
{
AssertSingle(argument);
var arg = this[argument];
return arg != null && arg[0].Equals("true", StringComparison.OrdinalIgnoreCase);
}
private void AssertSingle(string argument)
{
if (this[argument] != null && this[argument].Count > 1)
throw new ArgumentException(string.Format("{0} has been specified more than once, expecting single value", argument));
}
public string Single(string argument)
{
AssertSingle(argument);
//only return value if its NOT true, there is only a single item for that argument
//and the argument is defined
if (this[argument] != null && !IsTrue(argument))
return this[argument][0];
return null;
}
public bool Exists(string argument)
{
return (this[argument] != null && this[argument].Count > 0);
}
/// <summary>
/// Gets the <see cref="System.Collections.ObjectModel.Collection&lt;T&gt;"/> with the specified parameter.
/// </summary>
/// <value></value>
public Collection<string> this[string parameter]
{
get
{
return _parameters.ContainsKey(parameter) ? _parameters[parameter] : null;
}
}
}
}

861
BDF.cs Normal file
View File

@@ -0,0 +1,861 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Spire.Xls;
namespace bdf
{
public class Row //Generic Type 2
{
public Int32 Row_Number { get; set; } = 1;
public Int32 Record_Type { get; set; } = 2;
public Int32 Contractor_Billing_Account_Number { get; set; } = 857412;
public Int32 Invoice_Number { get; set; } = 61262091;
public Int32 Invoice_Period { get; set; } = 0;
public String Canada_Contract_Identifier { get; set; } = "X";
public String Contractor { get; set; } = "ROGERS";
public Int32 SSC_Order_Number { get; set; } = 0;
public Int32 SSC_Version { get; set; } = 0;
public Int32 SSC_Seq_No { get; set; } = 1;
public String SDPID { get; set; } = "X";
public String Department { get; set; } = "X";
public String Prov { get; set; } = "X";
public String Service_Project_ID { get; set; } = "";
public Int32 Billing_Effective_Date { get; set; } = 0;
public Int32 Billing_End_Date { get; set; } = 0;
public Int32 Billing_Cancel_Date { get; set; } = 0;
public Int32 Period_of_Service { get; set; } = 0;
public String SCID { get; set; } = "X";
public Int32 Quantity { get; set; } = 1;
public Double Recurring_Charges_for_the_Month { get; set; } = 0;
public Double Total_Recurring_Charges_for_the_Month { get; set; } = 0;
public Double Non_recurring_Charges_for_the_Month { get; set; } = 0;
public Double Total_Non_recurring_Charges_for_the_Month { get; set; } = 0;
public Double Total_Service_Credits { get; set; } = 0;
public Double Total_Other_Charges_and_Credits { get; set; } = 0;
public Double Total_GST_Amount { get; set; } = 0;
//public Double Total_PST_Amount { get; set; } = 0;
public Double Total_HST_Amount { get; set; } = 0;
public Double Total_QST_Amount { get; set; } = 0;
public Double Total_Taxes { get; set; } = 0;
public Double Total_Amount_including_taxes { get; set; } = 0;
public String CI_Name { get; set; } = "X";
public String CI_Name_2 { get; set; } = "";
public String TCID { get; set; } = "X";
public String PO_Number { get; set; } = "";
public String TA_Number { get; set; } = "X";
}
public class Row2 // Generic Type 1
{
public Int32 Record_Type { get; set; } = 1;
public Int32 Invoice_Date { get; set; } = 0;
public Int32 Invoice_Period { get; set; } = 0;
public String Canada_Contract_Identifier { get; set; } = "X";
public String Contractor_Name { get; set; } = "X";
public Int32 Total_Recurring_Charges_for_the_Month { get; set; } = 0;
public Int32 Total_Non_Recurring_Charges_for_the_Month { get; set; } = 0;
public Int32 Total_Charges_Excluding_Taxes { get; set; } = 0;
public Int32 Total_Other_Charges_and_Credits { get; set; } = 0;
public Int32 Total_Service_Credits { get; set; } = 0;
public Int32 Total_Late_Payment_Amount { get; set; } = 0;
public Int32 Total_GST_Amount { get; set; } = 0;
//public Int32 Total_PST_Amount { get; set; } = 0;
public Int32 Total_HST_Amount { get; set; } = 0;
public Int32 Total_QST_Amount { get; set; } = 0;
public Int32 Total_Taxes { get; set; } = 0;
public Int32 Total_Amount_Including_Taxes { get; set; } = 0;
public Int32 Total_Usage_Charges { get; set; } = 0; // Added because of SIP
}
public class Row3 // SIP Type 3
{
public Int32 Line_Number { get; set; } = 1;
public Int32 Record_Type { get; set; } = 0;
public Int32 Contractor_Billling_Account_Number { get; set; } = 0;
public Int32 Invoice_Number { get; set; } = 0;
public Int32 Invoice_Period { get; set; } = 0;
public String Canada_Contract_Identifier { get; set; } = "X";
public String Contractor { get; set; } = "X";
public String Period_of_Service { get; set; } = "X";
public String Department { get; set; } = "X";
public String SCID { get; set; } = "X";
public Int32 Total_Usage_Charges_for_the_Month { get; set; } = 0;
public Int32 Total_GST_Amount { get; set; } = 0;
//public Int32 Total_PST_Amount { get; set; } = 0;
public Int32 Total_HST_Amount { get; set; } = 0;
public Int32 Total_QST_Amount { get; set; } = 0;
public Int32 Total_Taxes { get; set; } = 0;
public Int32 Total_Amount_Including_Taxes { get; set; } = 0;
}
public class BDF
{
public static Row CopyRow(Row r)
{
Row n = new Row { };
n.Row_Number = r.Row_Number;
n.Record_Type = r.Record_Type;
n.Contractor_Billing_Account_Number = r.Contractor_Billing_Account_Number;
n.Invoice_Number = r.Invoice_Number;
n.Invoice_Period = r.Invoice_Period;
n.Canada_Contract_Identifier = r.Canada_Contract_Identifier;
n.Contractor = r.Contractor;
n.SSC_Order_Number = r.SSC_Order_Number;
n.SSC_Version = r.SSC_Version;
n.SSC_Seq_No = r.SSC_Seq_No;
n.SDPID = r.SDPID;
n.Department = r.Department;
n.Prov = r.Prov;
n.Service_Project_ID = r.Service_Project_ID;
n.Billing_Effective_Date = r.Billing_Effective_Date;
n.Billing_End_Date = r.Billing_End_Date;
n.Billing_Cancel_Date = r.Billing_Cancel_Date;
n.Period_of_Service = r.Period_of_Service;
n.SCID = r.SCID;
n.Quantity = r.Quantity;
n.Recurring_Charges_for_the_Month = r.Recurring_Charges_for_the_Month;
n.Total_Recurring_Charges_for_the_Month = n.Total_Recurring_Charges_for_the_Month;
n.Non_recurring_Charges_for_the_Month = r.Non_recurring_Charges_for_the_Month;
n.Total_Non_recurring_Charges_for_the_Month = r.Total_Non_recurring_Charges_for_the_Month;
n.Total_Service_Credits = r.Total_Service_Credits;
n.Total_Other_Charges_and_Credits = r.Total_Other_Charges_and_Credits;
n.Total_GST_Amount = r.Total_GST_Amount;
n.Total_HST_Amount = r.Total_HST_Amount;
//n.Total_PST_Amount = r.Total_PST_Amount; // do not uncomment creates a extra ghost column in output
n.Total_QST_Amount = r.Total_QST_Amount;
n.Total_Taxes = r.Total_Taxes;
n.Total_Amount_including_taxes = r.Total_Amount_including_taxes;
n.CI_Name = r.CI_Name;
n.CI_Name_2 = r.CI_Name_2;
n.TCID = r.TCID;
n.PO_Number = r.PO_Number;
n.TA_Number = r.TA_Number;
return n;
}
public static Spire.Xls.Workbook S_CreateBDF(string type)
{
if (type == "LDF" || type == "WAV")
return S_CreateBDF();
else if (type == "SIP")
return S_CreateBDFSIP();
else
return null;
}
public static Spire.Xls.Workbook S_CreateBDFSIP()
{
var workbook = new Spire.Xls.Workbook();
var worksheet1 = workbook.Worksheets.Add("BDF Type 1");
cleanSheets(ref workbook);
{
//Headers "SIP BDF Type 1"
worksheet1.Range[1, 1].Value = "Record Type";
worksheet1.Range[1, 2].Value = "Invoice Date";
worksheet1.Range[1, 3].Value = "Invoice Period";
worksheet1.Range[1, 4].Value = "Canada Contract Identifier";
worksheet1.Range[1, 5].Value = "Contractor";
worksheet1.Range[1, 6].Value = "Total Recurring Charges for the Month";
worksheet1.Range[1, 7].Value = "Total Non-Recurring Charges for the Month";
worksheet1.Range[1, 8].Value = "Total Charges Excluding Taxes";
worksheet1.Range[1, 9].Value = "Total Other Charges and Credits";
worksheet1.Range[1, 10].Value = "Total Service Credits";
worksheet1.Range[1, 11].Value = "Total Late Payment Amount";
worksheet1.Range[1, 12].Value = "Total GST Amount";
worksheet1.Range[1, 13].Value = "Total HST Amount";
worksheet1.Range[1, 14].Value = "Total QST Amount";
worksheet1.Range[1, 15].Value = "Total Taxes";
worksheet1.Range[1, 16].Value = "Total Amount Including Taxes";
worksheet1.Range[1, 17].Value = "Total Usage Charges"; // this line was the only delta
var worksheet2 = workbook.Worksheets.Add("BDF Type 2");
//Headers "BDF Type 2"
worksheet2.Range[1, 1].Value = "Line Number"; //slight change
worksheet2.Range[1, 2].Value = "Record Type";
worksheet2.Range[1, 3].Value = "Contractor Billing Account Number";
worksheet2.Range[1, 4].Value = "Invoice Number";
worksheet2.Range[1, 5].Value = "Invoice Period";
worksheet2.Range[1, 6].Value = "Canada Contract Identifier";
worksheet2.Range[1, 7].Value = "Contractor";
worksheet2.Range[1, 8].Value = "SSC Reference Number"; //slight change
worksheet2.Range[1, 9].Value = "SSC Version";
worksheet2.Range[1, 10].Value = "SSC Seq No";
worksheet2.Range[1, 11].Value = "SDPID";
worksheet2.Range[1, 12].Value = "Department";
worksheet2.Range[1, 13].Value = "Prov";
worksheet2.Range[1, 14].Value = "Service Project ID";
worksheet2.Range[1, 15].Value = "Billing Effective Date";
worksheet2.Range[1, 16].Value = "Billing End Date";
worksheet2.Range[1, 17].Value = "Billing Cancel Date";
worksheet2.Range[1, 18].Value = "Period of Service";
worksheet2.Range[1, 19].Value = "SCID";
worksheet2.Range[1, 20].Value = "Qty"; //slight change
worksheet2.Range[1, 21].Value = "Recurring Charges for the Month";
worksheet2.Range[1, 22].Value = "Total Recurring Charges for the Month";
worksheet2.Range[1, 23].Value = "Non-recurring Charges for the Month";
worksheet2.Range[1, 24].Value = "Total Non-recurring Charges for the Month";
worksheet2.Range[1, 25].Value = "Total Service Credits";
worksheet2.Range[1, 26].Value = "Total Other Charges and Credits";
worksheet2.Range[1, 27].Value = "Total GST Amount";
worksheet2.Range[1, 28].Value = "Total HST Amount";
worksheet2.Range[1, 29].Value = "Total QST Amount";
worksheet2.Range[1, 30].Value = "Total Taxes";
worksheet2.Range[1, 31].Value = "Total Amount including taxes";
worksheet2.Range[1, 32].Value = "CI Name";
worksheet2.Range[1, 33].Value = "CI Name 2";
worksheet2.Range[1, 34].Value = "TCID";
worksheet2.Range[1, 35].Value = "PO #"; //slight change
// worksheet2.Range[1, 36].Value = "TA Number"; //this line removed for SIP-2
var worksheet3 = workbook.Worksheets.Add("BDF Type 3");
//Headers "SIP BDF Type 3"
worksheet3.Range[1, 1].Value = "Line Number";
worksheet3.Range[1, 2].Value = "Record Type";
worksheet3.Range[1, 3].Value = "Contractor Billing Account Number";
worksheet3.Range[1, 4].Value = "Invoice Number";
worksheet3.Range[1, 5].Value = "Invoice Period";
worksheet3.Range[1, 6].Value = "Canada Contract Identifier";
worksheet3.Range[1, 7].Value = "Contractor";
worksheet3.Range[1, 8].Value = "Period of Service";
worksheet3.Range[1, 9].Value = "Department";
worksheet3.Range[1, 10].Value = "SCID";
worksheet3.Range[1, 11].Value = "Total Usage Charges for the Month";
worksheet3.Range[1, 12].Value = "Total GST Amount";
worksheet3.Range[1, 13].Value = "Total HST Amount";
worksheet3.Range[1, 14].Value = "Total QST Amount";
worksheet3.Range[1, 15].Value = "Total Taxes";
worksheet3.Range[1, 16].Value = "Total Amount including taxes";
}
Logger.Log(0, "Excel BDF template file created! {0}", bdf.dirpath + bdf.filename);
return workbook;
}
public static Spire.Xls.Workbook S_CreateBDF()
{
var workbook = new Spire.Xls.Workbook();
//using (var workbook = new XLWorkbook())
//Console.WriteLine("WS Count = {0}", workbook.Worksheets.Count);
var worksheet1 = workbook.Worksheets.Add("BDF Type 1");
cleanSheets(ref workbook);
{
//Headers "BDF Type 1"
worksheet1.Range[1, 1].Value = "Record Type";
worksheet1.Range[1, 2].Value = "Invoice Date";
worksheet1.Range[1, 3].Value = "Invoice Period";
worksheet1.Range[1, 4].Value = "Canada Contract Identifier";
worksheet1.Range[1, 5].Value = "Contractor";
worksheet1.Range[1, 6].Value = "Total Recurring Charges for the Month";
worksheet1.Range[1, 7].Value = "Total Non-Recurring Charges for the Month";
worksheet1.Range[1, 8].Value = "Total Charges Excluding Taxes";
worksheet1.Range[1, 9].Value = "Total Other Charges and Credits";
worksheet1.Range[1, 10].Value = "Total Service Credits";
worksheet1.Range[1, 11].Value = "Total Late Payment Amount";
worksheet1.Range[1, 12].Value = "Total GST Amount";
worksheet1.Range[1, 13].Value = "Total HST Amount";
worksheet1.Range[1, 14].Value = "Total QST Amount";
worksheet1.Range[1, 15].Value = "Total Taxes";
worksheet1.Range[1, 16].Value = "Total Amount Including Taxes";
var worksheet2 = workbook.Worksheets.Add("BDF Type 2");
//Headers "BDF Type 2"
worksheet2.Range[1, 1].Value = "Row Number";
worksheet2.Range[1, 2].Value = "Record Type";
worksheet2.Range[1, 3].Value = "Contractor Billing Account Number";
worksheet2.Range[1, 4].Value = "Invoice Number";
worksheet2.Range[1, 5].Value = "Invoice Period";
worksheet2.Range[1, 6].Value = "Canada Contract Identifier";
worksheet2.Range[1, 7].Value = "Contractor";
worksheet2.Range[1, 8].Value = "SSC Order Number";
worksheet2.Range[1, 9].Value = "SSC Version";
worksheet2.Range[1, 10].Value = "SSC Seq No";
worksheet2.Range[1, 11].Value = "SDPID";
worksheet2.Range[1, 12].Value = "Department";
worksheet2.Range[1, 13].Value = "Prov";
worksheet2.Range[1, 14].Value = "Service Project ID";
worksheet2.Range[1, 15].Value = "Billing Effective Date";
worksheet2.Range[1, 16].Value = "Billing End Date";
worksheet2.Range[1, 17].Value = "Billing Cancel Date";
worksheet2.Range[1, 18].Value = "Period of Service";
worksheet2.Range[1, 19].Value = "SCID";
worksheet2.Range[1, 20].Value = "Quantity";
worksheet2.Range[1, 21].Value = "Recurring Charges for the Month";
worksheet2.Range[1, 22].Value = "Total Recurring Charges for the Month";
worksheet2.Range[1, 23].Value = "Non-recurring Charges for the Month";
worksheet2.Range[1, 24].Value = "Total Non-recurring Charges for the Month";
worksheet2.Range[1, 25].Value = "Total Service Credits";
worksheet2.Range[1, 26].Value = "Total Other Charges and Credits";
worksheet2.Range[1, 27].Value = "Total GST Amount";
worksheet2.Range[1, 28].Value = "Total HST Amount";
worksheet2.Range[1, 29].Value = "Total QST Amount";
worksheet2.Range[1, 30].Value = "Total Taxes";
worksheet2.Range[1, 31].Value = "Total Amount including taxes";
worksheet2.Range[1, 32].Value = "CI Name";
worksheet2.Range[1, 33].Value = "CI Name 2";
worksheet2.Range[1, 34].Value = "TCID";
worksheet2.Range[1, 35].Value = "PO Number";
worksheet2.Range[1, 36].Value = "TA Number";
}
Logger.Log(0, "Excel BDF template file created! {0}", bdf.dirpath + bdf.filename);
return workbook;
}
public static void S_InsertData<T>(Spire.Xls.Worksheet worksheet, List<T> items)
{
/// <summary>
/// Inserts a list of objects (T) into a worksheet with headers.
/// Each property becomes a column, each object becomes a row.
/// </summary>
if (worksheet == null)
throw new ArgumentNullException(nameof(worksheet));
if (items == null)
throw new ArgumentNullException(nameof(items));
if (items.Count == 0)
return;
// Get properties of T
PropertyInfo[] props = typeof(T).GetProperties(
BindingFlags.Public | BindingFlags.Instance);
// No properties → nothing to insert
if (props.Length == 0)
return;
int startRow = 1; // Header row
int startCol = 1;
// -----------------------------------------
// Write header row
// -----------------------------------------
/*
for (int col = 0; col < props.Length; col++)
{
Spire.Xls.CellRange cell = worksheet.Range[startRow, startCol + col];
cell.Text = props[col].Name;
cell.Style.Font.IsBold = true;
}
*/
// -----------------------------------------
// Write data rows
// -----------------------------------------
for (int row = 0; row < items.Count; row++)
{
T item = items[row];
int excelRow = startRow + 1 + row;
for (int col = 0; col < props.Length; col++)
{
Spire.Xls.CellRange cell = worksheet.Range[excelRow, startCol + col];
object value = props[col].GetValue(item);
if (value == null)
{
cell.Text = string.Empty;
continue;
}
// Write numeric values as numbers. either Int32 or Double
if (
value is byte || value is short || value is int // ||
//value is long || value is float || value is double || value is decimal
)
{
cell.NumberValue = Convert.ToInt32(value);
}
else if (
//value is byte || value is short || value is int ||
value is long || value is float || value is double || value is decimal
)
{
cell.NumberValue = Convert.ToDouble(value);
}
else
{
cell.Text = value.ToString();
}
}
}
// Total number of rows written (header + items)
int totalRows = 1 + items.Count;
int totalCols = props.Length;
// ------------------------------------------------------
// Create a table format
// ------------------------------------------------------
Spire.Xls.CellRange tableRange = worksheet.Range[startRow, startCol, totalRows, totalCols];
TableFormatter.ApplyTableFormat(tableRange);
// ------------------------------------------
// Autofit column widths to contents
// ------------------------------------------
//worksheet.AllocatedRange.AutoFitColumns();
}
public static class TableFormatter
{
/// <summary>
/// Applies "table-style" formatting to a specified range:
/// - Bold gray header row
/// - Bordered cells
/// - Alternating (banded) row background colors
/// Fully compatible with FreeSpire.XLS.
/// </summary>
/// <param name="range">Spire.Xls.CellRange to format</param>
///
// Spire.Xls.Worksheet sheet = wb.Worksheets[0];
// Define a range with header + rows
// Spire.Xls.CellRange tableRange = sheet.Range["A1:D10"];
// Apply table styling
// TableFormatter.ApplyTableFormat(tableRange);
public static void ApplyTableFormat(Spire.Xls.CellRange range)
{
if (range == null)
throw new System.ArgumentNullException("range");
int rowCount = range.RowCount;
int colCount = range.ColumnCount;
if (rowCount == 0 || colCount == 0)
return;
// ---------------------------
// 1. Format Header Row
// ---------------------------
for (int col = 0; col < colCount; col++)
{
Spire.Xls.CellRange headerCell =
range[1, col + 1]; // 1-based indexing inside CellRange segment
headerCell.Style.Font.IsBold = true;
headerCell.Style.Color = System.Drawing.Color.LightGray;
headerCell.Style.Borders.LineStyle = Spire.Xls.LineStyleType.Thin;
headerCell.Borders[Spire.Xls.BordersLineType.DiagonalDown].LineStyle = Spire.Xls.LineStyleType.None;
headerCell.Borders[Spire.Xls.BordersLineType.DiagonalUp].LineStyle = Spire.Xls.LineStyleType.None;
}
// ---------------------------
// 2. Format Data Rows (banded)
// ---------------------------
for (int row = 2; row <= rowCount; row++)
{
bool isEven = (row % 2 == 0);
System.Drawing.Color rowColor = isEven
? System.Drawing.Color.FromArgb(245, 245, 245) // light gray band
: System.Drawing.Color.White;
for (int col = 1; col <= colCount; col++)
{
Spire.Xls.CellRange cell = range[row, col];
cell.Style.Color = rowColor;
cell.Style.Borders.LineStyle = Spire.Xls.LineStyleType.Thin;
cell.Borders[Spire.Xls.BordersLineType.DiagonalDown].LineStyle = Spire.Xls.LineStyleType.None;
cell.Borders[Spire.Xls.BordersLineType.DiagonalUp].LineStyle = Spire.Xls.LineStyleType.None;
}
}
// ---------------------------
// 3. Auto-fit column widths
// ---------------------------
range.AutoFitColumns();
}
}
public static void cleanSheets(ref Spire.Xls.Workbook workbook)
{
// Spire worksheets come with 3 default sheets, Sheet1, Sheet2 and Sheet3
// So we pop them off the stack, one at a time, the first time we add our own sheet to the Workbook
workbook.Worksheets.RemoveAt(0);
workbook.Worksheets.RemoveAt(0);
workbook.Worksheets.RemoveAt(0);
}
/*
public static XLWorkbook CreateBDF(string type)
{
if (type == "LDF" || type == "WAV")
return CreateBDF();
else if (type == "SIP")
return CreateBDFSIP();
else
return null;
}
public static XLWorkbook CreateBDF()
{
var workbook = new XLWorkbook();
//using (var workbook = new XLWorkbook())
{
var worksheet1 = workbook.Worksheets.Add("BDF Type 1");
//Headers "BDF Type 1"
worksheet1.Cell(1, 1).Value = "Record Type";
worksheet1.Cell(1, 2).Value = "Invoice Date";
worksheet1.Cell(1, 3).Value = "Invoice Period";
worksheet1.Cell(1, 4).Value = "Canada Contract Identifier";
worksheet1.Cell(1, 5).Value = "Contractor Name";
worksheet1.Cell(1, 6).Value = "Total Recurring Charges for the Month";
worksheet1.Cell(1, 7).Value = "Total Non-Recurring Charges for the Month";
worksheet1.Cell(1, 8).Value = "Total Charges Excluding Taxes";
worksheet1.Cell(1, 9).Value = "Total Other Charges and Credits";
worksheet1.Cell(1, 10).Value = "Total Service Credits";
worksheet1.Cell(1, 11).Value = "Total Late Payment Amount";
worksheet1.Cell(1, 12).Value = "Total GST Amount";
worksheet1.Cell(1, 13).Value = "Total HST Amount";
worksheet1.Cell(1, 14).Value = "Total QST Amount";
worksheet1.Cell(1, 15).Value = "Total Taxes";
worksheet1.Cell(1, 16).Value = "Total Amount Including Taxes";
var worksheet2 = workbook.Worksheets.Add("BDF Type 2");
//Headers "BDF Type 2"
worksheet2.Cell(1, 1).Value = "Row Number";
worksheet2.Cell(1, 2).Value = "Record Type";
worksheet2.Cell(1, 3).Value = "Contractor Billing Account Number";
worksheet2.Cell(1, 4).Value = "Invoice Number";
worksheet2.Cell(1, 5).Value = "Invoice Period";
worksheet2.Cell(1, 6).Value = "Canada Contract Identifier";
worksheet2.Cell(1, 7).Value = "Contractor";
worksheet2.Cell(1, 8).Value = "SSC Order Number";
worksheet2.Cell(1, 9).Value = "SSC Version";
worksheet2.Cell(1, 10).Value = "SSC Seq No";
worksheet2.Cell(1, 11).Value = "SDPID";
worksheet2.Cell(1, 12).Value = "Department";
worksheet2.Cell(1, 13).Value = "Prov";
worksheet2.Cell(1, 14).Value = "Service Project ID";
worksheet2.Cell(1, 15).Value = "Billing Effective Date";
worksheet2.Cell(1, 16).Value = "Billing End Date";
worksheet2.Cell(1, 17).Value = "Billing Cancel Date";
worksheet2.Cell(1, 18).Value = "Period of Service";
worksheet2.Cell(1, 19).Value = "SCID";
worksheet2.Cell(1, 20).Value = "Quantity";
worksheet2.Cell(1, 21).Value = "Recurring Charges for the Month";
worksheet2.Cell(1, 22).Value = "Total Recurring Charges for the Month";
worksheet2.Cell(1, 23).Value = "Non-recurring Charges for the Month";
worksheet2.Cell(1, 24).Value = "Total Non-recurring Charges for the Month";
worksheet2.Cell(1, 25).Value = "Total Service Credits";
worksheet2.Cell(1, 26).Value = "Total Other Charges and Credits";
worksheet2.Cell(1, 27).Value = "Total GST Amount";
worksheet2.Cell(1, 28).Value = "Total HST Amount";
worksheet2.Cell(1, 29).Value = "Total QST Amount";
worksheet2.Cell(1, 30).Value = "Total Taxes";
worksheet2.Cell(1, 31).Value = "Total Amount including taxes";
worksheet2.Cell(1, 32).Value = "CI Name";
worksheet2.Cell(1, 33).Value = "CI Name 2";
worksheet2.Cell(1, 34).Value = "TCID";
worksheet2.Cell(1, 35).Value = "PO Number";
worksheet2.Cell(1, 36).Value = "TA Number";
}
Logger.Log(0, "Excel BDF template file created! {0}", bdf.dirpath + bdf.filename);
return workbook;
}
public static XLWorkbook CreateBDFSIP()
{
var workbook = new XLWorkbook();
//using (var workbook = new XLWorkbook())
{
var worksheet1 = workbook.Worksheets.Add("BDF Type 1");
//Headers "SIP BDF Type 1"
worksheet1.Cell(1, 1).Value = "Record Type";
worksheet1.Cell(1, 2).Value = "Invoice Date";
worksheet1.Cell(1, 3).Value = "Invoice Period";
worksheet1.Cell(1, 4).Value = "Canada Contract Identifier";
worksheet1.Cell(1, 5).Value = "Contractor";
worksheet1.Cell(1, 6).Value = "Total Recurring Charges for the Month";
worksheet1.Cell(1, 7).Value = "Total Non-Recurring Charges for the Month";
worksheet1.Cell(1, 8).Value = "Total Charges Excluding Taxes";
worksheet1.Cell(1, 9).Value = "Total Other Charges and Credits";
worksheet1.Cell(1, 10).Value = "Total Service Credits";
worksheet1.Cell(1, 11).Value = "Total Late Payment Amount";
worksheet1.Cell(1, 12).Value = "Total GST Amount";
worksheet1.Cell(1, 13).Value = "Total HST Amount";
worksheet1.Cell(1, 14).Value = "Total QST Amount";
worksheet1.Cell(1, 15).Value = "Total Taxes";
worksheet1.Cell(1, 16).Value = "Total Amount Including Taxes";
worksheet1.Cell(1, 17).Value = "Total Usage Charges"; // this line was the only delta
var worksheet2 = workbook.Worksheets.Add("BDF Type 2");
//Headers "BDF Type 2"
worksheet2.Cell(1, 1).Value = "Line Number"; //slight change
worksheet2.Cell(1, 2).Value = "Record Type";
worksheet2.Cell(1, 3).Value = "Contractor Billing Account Number";
worksheet2.Cell(1, 4).Value = "Invoice Number";
worksheet2.Cell(1, 5).Value = "Invoice Period";
worksheet2.Cell(1, 6).Value = "Canada Contract Identifier";
worksheet2.Cell(1, 7).Value = "Contractor";
worksheet2.Cell(1, 8).Value = "SSC Reference Number"; //slight change
worksheet2.Cell(1, 9).Value = "SSC Version";
worksheet2.Cell(1, 10).Value = "SSC Seq No";
worksheet2.Cell(1, 11).Value = "SDPID";
worksheet2.Cell(1, 12).Value = "Department";
worksheet2.Cell(1, 13).Value = "Prov";
worksheet2.Cell(1, 14).Value = "Service Project ID";
worksheet2.Cell(1, 15).Value = "Billing Effective Date";
worksheet2.Cell(1, 16).Value = "Billing End Date";
worksheet2.Cell(1, 17).Value = "Billing Cancel Date";
worksheet2.Cell(1, 18).Value = "Period of Service";
worksheet2.Cell(1, 19).Value = "SCID";
worksheet2.Cell(1, 20).Value = "Qty"; //slight change
worksheet2.Cell(1, 21).Value = "Recurring Charges for the Month";
worksheet2.Cell(1, 22).Value = "Total Recurring Charges for the Month";
worksheet2.Cell(1, 23).Value = "Non-recurring Charges for the Month";
worksheet2.Cell(1, 24).Value = "Total Non-recurring Charges for the Month";
worksheet2.Cell(1, 25).Value = "Total Service Credits";
worksheet2.Cell(1, 26).Value = "Total Other Charges and Credits";
worksheet2.Cell(1, 27).Value = "Total GST Amount";
worksheet2.Cell(1, 28).Value = "Total HST Amount";
worksheet2.Cell(1, 29).Value = "Total QST Amount";
worksheet2.Cell(1, 30).Value = "Total Taxes";
worksheet2.Cell(1, 31).Value = "Total Amount including taxes";
worksheet2.Cell(1, 32).Value = "CI Name";
worksheet2.Cell(1, 33).Value = "CI Name 2";
worksheet2.Cell(1, 34).Value = "TCID";
worksheet2.Cell(1, 35).Value = "PO #"; //slight change
// worksheet2.Cell(1, 36).Value = "TA Number"; //this line removed for SIP-2
var worksheet3 = workbook.Worksheets.Add("BDF Type 3");
//Headers "SIP BDF Type 3"
worksheet3.Cell(1, 1).Value = "Line Number";
worksheet3.Cell(1, 2).Value = "Record Type";
worksheet3.Cell(1, 3).Value = "Contractor Billing Account Number";
worksheet3.Cell(1, 4).Value = "Invoice Number";
worksheet3.Cell(1, 5).Value = "Invoice Period";
worksheet3.Cell(1, 6).Value = "Canada Contract Identifier";
worksheet3.Cell(1, 7).Value = "Contractor";
worksheet3.Cell(1, 8).Value = "Period of Service";
worksheet3.Cell(1, 9).Value = "Department";
worksheet3.Cell(1, 10).Value = "SCID";
worksheet3.Cell(1, 11).Value = "Total Usage Charges for the Month";
worksheet3.Cell(1, 12).Value = "Total GST Amount";
worksheet3.Cell(1, 13).Value = "Total HST Amount";
worksheet3.Cell(1, 14).Value = "Total QST Amount";
worksheet3.Cell(1, 15).Value = "Total Taxes";
worksheet3.Cell(1, 16).Value = "Total Amount including taxes";
}
Logger.Log(0, "Excel BDF template file created! {0}", bdf.dirpath + bdf.filename);
return workbook;
}
public static void InsertData<T>(IXLWorksheet worksheet, List<T> items)
{
if (items == null || items.Count == 0)
return;
var type = typeof(T);
var props = type.GetProperties();
//Logger.Log(0, "prop={0} items={1}", props.Length, items.Count);
// Write headers
//for (int i = 0; i < props.Length; i++)
//{
// //Logger.Log(0, "name={0}", props[i].Name);
// worksheet.Cell(1, i + 1).Value = props[i].Name;
// worksheet.Cell(1, i + 1).Style.Font.Bold = true;
//}
// Write data
for (int r = 0; r < items.Count; r++)
{
for (int c = 0; c < props.Length; c++)
{
//if (props[c].Name == "Total_PST_Amount") continue;
//Logger.Log(0, "value={0}", props[c].GetValue(items[r], null));
var value = props[c].GetValue(items[r], null);
//Console.WriteLine("props {0}:{1}", props[c].Name, value);
if (props[c].Name.ToString() == "Billing_Cancel_Date") // GOC wants this field bank instead of 0
{
//Console.WriteLine("skip");
continue;
}
//Logger.Log(0, "Type={0}", value.GetType().Name);
try
{
if (value.GetType().Name == "Int32")
{
worksheet.Cell(r + 2, c + 1).Value = (Int32)value;
}
else if (value.GetType().Name == "String")
{
worksheet.Cell(r + 2, c + 1).Value = (String)value;
}
else if (value.GetType().Name == "Double")
{
worksheet.Cell(r + 2, c + 1).Value = (Double)value;
}
else
{
worksheet.Cell(r + 2, c + 1).Value = "z";
}
}
catch (Exception e)
{
Logger.Log(0, "Exception: {0} : {1} !", e.Message, e.InnerException);
}
}
}
// Format table
//Logger.Log("Making range");
var range = worksheet.Range(1, 1, items.Count + 1, props.Length);
//Logger.Log("Making table");
range.CreateTable();
worksheet.Columns().AdjustToContents();
}
public class ListObject
{
public string Name { get; private set; }
public Spire.Xls.Worksheet Sheet { get; private set; }
public CellRange Range { get; private set; }
public ListObject(string name)
{
Name = name;
}
/// <summary>
/// Creates a fake ListObject-style table at the given worksheet and row/column.
/// </summary>
public void CreateTable<T>(Spire.Xls.Worksheet sheet, int startRow, int startCol, List<T> items)
{
Sheet = sheet;
if (items == null || items.Count == 0)
throw new ArgumentException("Items list must contain at least one element.");
PropertyInfo[] props = typeof(T)
.GetProperties(BindingFlags.Public | BindingFlags.Instance);
int row = startRow;
int col = startCol;
// ---------------------------------------------------
// HEADER ROW
// ---------------------------------------------------
for (int i = 0; i < props.Length; i++)
{
CellRange cell = sheet.Range[row, col + i];
cell.Text = props[i].Name;
cell.Style.Font.IsBold = true;
cell.Style.Color = System.Drawing.Color.LightGray;
cell.Style.Borders.LineStyle = LineStyleType.Thin;
}
row++;
// ---------------------------------------------------
// DATA ROWS
// ---------------------------------------------------
int dataStartRow = row;
int itemIndex = 0;
foreach (T item in items)
{
for (int i = 0; i < props.Length; i++)
{
object value = props[i].GetValue(item, null);
CellRange cell = sheet.Range[row, col + i];
cell.Value2 = value;
// Border
cell.Style.Borders.LineStyle = LineStyleType.Thin;
// Alternating (banded) rows
if (itemIndex % 2 == 0)
cell.Style.Color = System.Drawing.Color.White;
else
cell.Style.Color = System.Drawing.Color.FromArgb(245, 245, 245);
}
itemIndex++;
row++;
}
int lastRow = row - 1;
int lastCol = col + props.Length - 1;
// Record the table's occupied range
Range = sheet.Range[startRow, startCol, lastRow, lastCol];
// ---------------------------------------------------
// AUTO-FIT WIDTHS
// ---------------------------------------------------
Range.AutoFitColumns();
}
/// <summary>
/// Updates all values in an existing fake ListObject.
/// </summary>
public void Refresh<T>(List<T> items)
{
if (Sheet == null || Range == null)
throw new InvalidOperationException("Table has not been created.");
PropertyInfo[] props = typeof(T)
.GetProperties(BindingFlags.Public | BindingFlags.Instance);
int headerRow = Range.Row;
int dataStartRow = headerRow + 1;
int row = dataStartRow;
int col = Range.Column;
foreach (T item in items)
{
for (int i = 0; i < props.Length; i++)
{
object value = props[i].GetValue(item, null);
Sheet.Range[row, col + i].Value2 = value;
}
row++;
}
}
}
*/
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Embedded/Renci.SshNet.dll Executable file

Binary file not shown.

BIN
Embedded/Spire.XLS.dll Executable file

Binary file not shown.

BIN
Embedded/System.Buffers.dll Executable file

Binary file not shown.

BIN
Embedded/System.Formats.Asn1.dll Executable file

Binary file not shown.

BIN
Embedded/System.Memory.dll Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Embedded/System.ValueTuple.dll Executable file

Binary file not shown.

BIN
Embedded/arial.ttf Executable file

Binary file not shown.

View File

@@ -0,0 +1,26 @@
PuTTY-User-Key-File-3: ssh-rsa
Encryption: none
Comment: rsa-key-20251222
Public-Lines: 6
AAAAB3NzaC1yc2EAAAADAQABAAABAQCkhl4EpiCvmTBENERzih8VHL4AzDJfm08e
mA+PYg+mWhrM8eZ79zuAdy6NJHlyP0ccdycujqpMAV8EBRZGxqSf74sBQhg9+tzV
0k2oALfV0CznOX3Fn1QEl3d3f3eNe5O1e7VipKBTGz9CGfTE2MIS3cnYU2g3LtoD
55sKjXXnUIPRy7YCCK8Rsd/bZITJMX6A5FhBpyuMl0szTf5XI4p/hBW/S9lOiGBc
AATL+jctjXz7bj6PjCvEBlINXct5h3u7xoL6wNxx9lRayEWRaManYczhXsy9ZaFU
2TUQYFSN5VTJVIQ8X2Uaip+uPimikdrXImOA51FAUri5esJceuVB
Private-Lines: 14
AAABAEW3doGrz+/5Dv3n1BXNsqwkmNMHtFTVICrLrtRIbm9EgVTVMKDZPAqM9lny
2c+yxrRmPWE6LSm17whqC22EYWAwhovK8TDaa9fjnOqTG1NsOorkzsn+YQDtGj+1
8PgwJIBj4pHhRtrQkfa1vwXnAB40g4K6nU+8979t1kIbfZm905+esCE2i384U4HZ
EdxxqJjiT/qSyWJzCocqdEc7/u8wQbbBJa2ES9i/ABh94o0/Yn2Ub8hknIYKCte2
zzlGlLHQ1r5JxkXEWQhEanv4YX7cmr3KIpz5KZLWm1M/0iD83Ih9mUe8pfLYBMWM
Ey04F+vtXOKkmWho3+9BipepJREAAACBAM1w11la3UhGujE/bxDwdawUPiC5lZaN
4MdsdQ4aAsEMFabRpdR8ZIL4QEIZw73+NEAOiBcc7OpiylMO5Areya4lZ2FPE39e
T0Z/fyqlvYGzSYg4L8f10r56uhwbhsSJRGdrRJfgukHNVjqi14MCN78Ujn/DbjdD
JYpJleAKaS1NAAAAgQDNA772ganZ1rjvmwEGLCBbFtQGDuf6/iMyuAGWObb8zdea
76ZwWtZ3DFotSD/K6ajBzCzH7ghJ9L1URjl0pTJb4Gq5Eel61maaG0ijJ02ZMmQL
vme8Hs7h95J2XcVHaF7DVpNlY/hFXiEyVsVTKWD3LDKhLNM1nbD2WiAafqatxQAA
AIEAp/ot6RXzIHO9o8dfXibt/HPgz3Ulq9jLEUiMHT7oamXyvqDfdFC4QBwxGwnX
J7bzDV2FdwLv3Jsv+s90vnQiHf1/wzW9msT7wyyp1FCV8kQaVwcGEC6Ie1ihh3vN
gZ86hvEdbYMvFIRCheMjoTAJ9BywKQjlq2xaJ8wNGYyunKA=
Private-MAC: 8fb0374e7e484491cc9a5bc9b649605a7f9da3a8e07580b0c6b60dd6464569f6

View File

@@ -0,0 +1,31 @@
PuTTY-User-Key-File-3: ssh-rsa
Encryption: aes256-cbc
Comment: rsa-key-20251222
Public-Lines: 6
AAAAB3NzaC1yc2EAAAADAQABAAABAQCkhl4EpiCvmTBENERzih8VHL4AzDJfm08e
mA+PYg+mWhrM8eZ79zuAdy6NJHlyP0ccdycujqpMAV8EBRZGxqSf74sBQhg9+tzV
0k2oALfV0CznOX3Fn1QEl3d3f3eNe5O1e7VipKBTGz9CGfTE2MIS3cnYU2g3LtoD
55sKjXXnUIPRy7YCCK8Rsd/bZITJMX6A5FhBpyuMl0szTf5XI4p/hBW/S9lOiGBc
AATL+jctjXz7bj6PjCvEBlINXct5h3u7xoL6wNxx9lRayEWRaManYczhXsy9ZaFU
2TUQYFSN5VTJVIQ8X2Uaip+uPimikdrXImOA51FAUri5esJceuVB
Key-Derivation: Argon2id
Argon2-Memory: 8192
Argon2-Passes: 34
Argon2-Parallelism: 1
Argon2-Salt: 8cc26a979c9bde54fbc3fcb4e04734eb
Private-Lines: 14
svCLtLXDHcRYZRhwDP+9/VZu8gw7EY5ONC/tIZbcQr9JE52fcfPkUt2YHSxptOfB
X9W0wUzryh9pbRULWbQcdP8slfBsfPmMK5REWudTFMqDosvxTSAHwDwCXdgpJnpV
TgrWJ+NROEy4pIETl0o7x1kIo9UQtXkUhavejaRXZm33cltzA6ciZvET7eQRuTbP
qSEW2Ul4h/JFMhadb0PzDUHDXmIIvZV7HqDhE9aBYE0qorMNA/4hWgEMuoKN5CfO
hW9RouYKWJ64hVN4yff9zTMI8hp9C0NgF8aqiJFjUzaIbvyzfhCQ36U7aSg/ELvq
tgk2N1+YWR8bOairpTmew13qOtyMiejl5RszTjwtv6HgMuZIxxjcDBkpnH6IAid/
TrnOemr7caJKuwl13gcjowvNzzDNNqRJo8rAx9iMieqTGUu05m0oCpWHmVjzuffz
m1V0EFF+DUo4mGVzlXvMUb1e0VNOTcCK8yyU7QqsiqEmapGaiKdfRWadLi/KM/+D
e5jxG7NfbpzJiF+nQN/krS+obP7iC4O+OG7Sq3fRWiLVTd68HS2sYFOR5e9Lrpz3
AiGIOV8blsbIn2ZNTIIB8dCFmoYg8N8FNDmzbhp25iBoEWXWLWsmGkY0peTK1XL7
r/CU3S4MqJeVRFawT+llBuq8yohgtr4Mka+OWeEbMC3ko1eRCFlaQSXdvUV2+f+b
KHyNSq0T/6yGv3xFCWP9qwerUswpW0Qr9BjV+wPnAHPc00F/2Q/7UGg3EAHhYH+A
bbn/vX6whhUeetXLIxPQgiM1XEPsEp9EKDmZZNr9BVjDOULgz473UXor4RglTnXC
PWWPcmGKuuBrKHxtbbyYP1Cjoa2CbVQ5E9mutkGIQTe9hnXQZF0XEKGqsJ8M1wQ8
Private-MAC: 6ef2b36c3493d513e8d4bbc9714c1f616320a22a7e453eb298db373e6d7b667f

9
Embedded/public_Rogers1! Normal file
View File

@@ -0,0 +1,9 @@
---- BEGIN SSH2 PUBLIC KEY ----
Comment: "rsa-key-20251222"
AAAAB3NzaC1yc2EAAAADAQABAAABAQCkhl4EpiCvmTBENERzih8VHL4AzDJfm08e
mA+PYg+mWhrM8eZ79zuAdy6NJHlyP0ccdycujqpMAV8EBRZGxqSf74sBQhg9+tzV
0k2oALfV0CznOX3Fn1QEl3d3f3eNe5O1e7VipKBTGz9CGfTE2MIS3cnYU2g3LtoD
55sKjXXnUIPRy7YCCK8Rsd/bZITJMX6A5FhBpyuMl0szTf5XI4p/hBW/S9lOiGBc
AATL+jctjXz7bj6PjCvEBlINXct5h3u7xoL6wNxx9lRayEWRaManYczhXsy9ZaFU
2TUQYFSN5VTJVIQ8X2Uaip+uPimikdrXImOA51FAUri5esJceuVB
---- END SSH2 PUBLIC KEY ----

BIN
Embedded/template.xlsx Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

124
FreeSpire.XLS.14.2.0/license.txt Executable file
View File

@@ -0,0 +1,124 @@
License Agreement
BY INSTALLING, DOWNLOADING, COPYING OR OTHERWISE USING THE PRODUCT, YOU AGREE TO BE BOUND BY THE TERMS OF THIS EULA. IF YOU DO NOT AGREE TO THE TERMS OF THIS EULA, DO NOT INSTALL, DOWNLOAD, COPY OR USE THE PRODUCT.
1. IMPORTANT NOTICE.
YOU SHOULD READ THE FOLLOWING TERMS AND CONDITIONS CAREFULLY BEFORE YOU DOWNLOAD, INSTALL OR USE E-ICEBLUE'S COMPONENT AND RELATED DOCUMENTATION (THE "LICENSED SOFTWARE") DISTRIBUTED UNDER THE TRADEMARK OF COMPONENT AND/OR E-ICEBLUE. BY INSTALLING OR USING THE LICENSED SOFTWARE, YOU AGREE TO BE BOUND BY THIS LICENSE AGREEMENT, AND ITS TERMS SHALL BE BINDING WITH RESPECT TO YOUR USE OF THE LICENSED SOFTWARE. IF YOU DO NOT AGREE TO THE FOLLOWING TERMS AND CONDITIONS, DO NOT INSTALL OR USE THE SOFTWARE.
2. DEFINITIONS.
A. "e-iceblue" means e-iceblue Corporation
B. "You" and "Your" mean the party purchasing a license to use the Licensed Software under the terms of this agreement.
C. "Application Programming Interface or API" means a publicly accessible interface defining the ways by which an application program may request services from libraries and/or software.
D. "Licensed Software" means compiled Objects, Modules, License Key and any and all updates thereto, together with all associated documentation provided by e-iceblue or its authorized resellers.
E. "License Key" means a unique code provided by e-iceblue or its authorized resellers which identifies You, as well as the license type, and which unlocks or enables certain features of the Licensed Software.
F. "Application" or "Your Application" means a software application that You develop which incorporates all or parts of the Licensed Software.
G. "Evaluation Trial Period" means a specified period of time during which You may temporarily use the Licensed Software for evaluation purposes only.
3. LICENSE GRANT.
The Cumulative License granted to You by e-iceblue is a combination of the Base License Grant, described in section (3A) below, which is common to every Licensed Software title covered by this agreement, and one or more supplemental License Grant which covers the specific product obtained by You from e-iceblue or its authorized resellers.
Four basic types of supplemental License Grants are described in sections (3B): Evaluation License, Developer License, Developer OEM License, Site Enterprise License, Site OEM License.
These five basic types are hereby further defined and/or restricted as to the number of developers, servers, geography locations and distribution method(s), depending on the specific product(s) being licensed by You.
The precise combination of the Base License Grant and one or more supplemental License Grant(s) obtained by You is identified by e-iceblue at the time of purchase or most recent upgrade.
3A. BASE LICENSE GRANT.
In consideration of Your payment of applicable license fees and/or Your acceptance of the terms of this Agreement, e-iceblue hereby grants to You certain nonexclusive and nontransferable rights limited by the terms of this Agreement.
The Licensed Software is licensed (not sold) to You, for use strictly under the terms of this Agreement, and e-iceblue reserves all rights not expressly granted to You herein. If You upgrade the Licensed Software to a higher-numbered version thereof or to a comparable E-iceblue product, this license is terminated and Your rights shall be limited to the license associated with the upgraded product or version.
In addition, You acknowledge that the Licensed Software may contain certain third party software components which are distributed under the terms of their own licenses.
3B. EVALUATION LICENSE.
In order to facilitate an efficient evaluation process of the Licensed Software by developers, e-iceblue may, at its discretion, provide specially designed, temporary License Key(s) that are encoded with an embedded expiration date.
The License granted in conjunction with such License Key(s) is considered temporary, and multiple developers may use it for the sole purpose of evaluating the Licensed Software during a specific Evaluation Trial Period. Licensed Evaluation Trial Software contains mechanisms that inhibit its ability to function at a later date.
It is Your responsibility to ensure that the Applications You create do not contain Licensed Evaluation Trial Software and that their ability to function at a later date is not inhibited or diminished.
3C. DEVELOPER LICENSE.
The following terms and conditions contained in this section (3C) apply to You ONLY if at the time of original purchase or most recent upgrade, the License granted to You by E-iceblue was defined as "Developer License".
The specific license level selected by you at the time of purchase or most recent upgrade determines whether the license applies to (1) a single named developer, or (2) a team of named developers, for example a Developer Team, or (3) a single site (facility or campus) whereby an unlimited number of developers located within said site (facility or campus) may be allowed access to the Licensed Software.
You are hereby granted a nonexclusive, royalty-free license to integrate the Licensed Software into Your Applications and to distribute such Licensed Software in connection with said Applications, provided that
(a) said Applications do not in any way compete with the Licensed Software, or provide substantially the same functionality as the Licensed Software, or expose the functionality of the Licensed Software through a programmable interface;
(b) each of Your Applications developed using Licensed Software is substantially larger, more complex, and contains a significantly wider range of functions as compared to the Licensed Software;
(c) each of Your Applications developed using Licensed Software is designed for end users, rather than for developers who would be able to build other software that would compete with the Licensed Software, and
(d) You do not permit further distribution of the Licensed Software by Your end users.
You may embed the License Keys in the Applications You distribute, provided that the following conditions are met:
(a) each such Application must be marked with a prominent copyright notice bearing Your name as declared by You during purchase of the License;
(b) the License Key may not be embedded in any such Application or distributed in any other manner that makes the License Key visible to the end user, and
(c) each such Application must include the following comment in its source code within close proximity to each copy of an embedded License Key: "This application utilizes a licensed copy of e-iceblue software, copyright (c) 2004-2018, which is the property of e-iceblue Corporation, www.e-iceblue.com. All rights are reserved by e-iceblue.
Use of any objects outside of the context of this application is a violation of United States and international copyright laws and other applicable laws."
For each License Key provided to You by e-iceblue, depending on the specific license level selected by you at the time of purchase or most recent upgrade, You are granted a nonexclusive License to make the Licensed Software and/or the License Key(s) available either to the specified number of Your named developers or to an unlimited number of Your developers located at a single site (facility or campus) as indicated by e-iceblue and further explained below.
Should either the number of named developers or the number of sites with access to the Licensed Software and/or the License Key(s) ever exceed the number indicated at the time of original purchase or most recent upgrade, You agree to inform E-iceblue of such change and to upgrade Your License accordingly by paying an upgrade fee to e-iceblue in a timely manner.
One Developer Subscription authorizes One developer to utilize our product to create unlimited number of applications which can be deployed at only One geography location within your organization. This type of license supports one server or multiple servers in the same place, which is/are used to host your web application.
One Developer OEM Subscription authorizes One developer to create any number of applications using our product which can be deployed at Unlimited geography locations. This type of license allows royalty-free distribution.
One Site Enterprise Subscription entitles up to 10 developers in the register enterprise to create an unlimited number of custom applications/service using our product. It allows deployment of any number of custom applications at up to 10 geography locations.
One Site Enterprise OEM Subscription authorizes up to 50 developers in the register organization to create an unlimited number of custom applications using our product. It allows royalty-free deployment of any number of custom applications to Unlimited geography locations.
4. RESTRICTIONS ON USE AND TRANSFER.
You may not sublicense, rent, lease, assign or otherwise transfer the Licensed Software or any of Your rights thereto, either in whole or in part, to anyone else, except that You may, after obtaining written permission from e-iceblue, permanently transfer the Licensed Software in its entirety, provided You retain no copies of the Licensed Software and the transferee agrees to the terms and conditions of this Agreement.
Use of the Licensed Software with a License Key obtained from a source other than e-iceblue or its authorized resellers is expressly and strictly forbidden. e-iceblue reserves the right to take any and all actions that e-iceblue, in its sole discretion, deems necessary to protect against, monitor and control the use of the Licensed Software with illegal License Keys.
You agree to ensure that anyone who uses any portion of the Licensed Software provided to You complies with the terms and conditions of this Agreement.
5. INTELLECTUAL PROPERTY RIGHTS.
You acknowledge that the Licensed Software contains copyrighted material, trade secrets, trademarks and other proprietary material of e-iceblue ("Confidential Information"), and is protected under United States and international copyright law and other applicable laws.
You may not engage in any unauthorized use or disclosure of any Confidential Information. You agree that the source code of the Licensed Software is confidential and proprietary to e-iceblue. Accordingly, You may not copy the Licensed Software, or decompile, disassemble, reverse engineer or create a derivative work based upon the Licensed Software, or authorize anyone else to do so.
You must reproduce and maintain all copyright notices that are contained in the Licensed Software on any copy thereof that You make or use.
6. TERM AND TERMINATION.
Except as otherwise provided in this Agreement, depending on the specific license level selected by you at the time of purchase or most recent upgrade, the term of the license granted herein is either perpetual, or alternatively the license is periodic, valid for a specific period of time, such as a month or a year.
The license becomes effective when You install or use the Licensed Software. You may terminate this license at any time by destroying any and all copies of the Licensed Software or by returning all such copies to e-iceblue.
This Agreement and the associated license for the Licensed Software will terminate automatically and without provision of notice by e-iceblue if You fail to comply with any of the terms or conditions of this Agreement or if You cease permanent use of the Licensed Software, for whatever reason.
Upon termination of this Agreement for any reason, You agree that You will destroy all copies of the Licensed Software or return all such copies to e-iceblue. In addition to this sentence and the previous sentence, Sections 4, 5 and 7-13 shall survive any termination of this Agreement.
7. LIMITED WARRANTY.
e-iceblue warrants that the Licensed Software will perform substantially in accordance with its accompanying documentation, when operated in the execution environment specified in such documentation, for the warranty period ending thirty (30) days following the date on which You first install or first use the Licensed Software.
This limited warranty is void if failure of the Licensed Software to conform to such warranty is caused in whole or in part by
(a) any defect in any hardware or other equipment used with the Licensed Software;
(b) any failure of any hardware or any other equipment used with the Licensed Software to function in accordance with applicable manufacturer's specifications for such items;
(c) any alteration, modification or enhancement of the Licensed Software by You or anyone other than e-iceblue;
(d) any failure by You or anyone else to follow e-iceblue's instructions with respect to proper use of the Licensed Software; or
(e) improper use, abuse, accident, neglect or negligence on the part of You or anyone other than e-iceblue.
e-iceblue will not be obligated to honor the limited warranty or provide any remedy thereunder unless the Licensed Software is returned to e-iceblue along with the original dated receipt.
Any replacement Licensed Software will be warranted for thirty (30) days following the date on which e-iceblue provides it to You.
EXCEPT AS OTHERWISE SET FORTH IN THIS AGREEMENT, THE LICENSED SOFTWARE IS PROVIDED TO YOU "AS IS", AND E-ICEBLUE MAKES NO EXPRESS OR IMPLIED WARRANTIES WHATSOEVER WITH RESPECT TO ITS FUNCTIONALITY, CONDITION, PERFORMANCE, OPERABILITY OR USE.
WITHOUT LIMITING THE FOREGOING, E-ICEBLUE DISCLAIMS ALL IMPLIED WARRANTIES INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR FREEDOM FROM INFRINGEMENT.
SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSIONS MAY NOT APPLY TO YOU.
THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL RIGHTS, AND YOU MAY ALSO HAVE OTHER RIGHTS THAT VARY FROM ONE JURISDICTION TO ANOTHER.
8. LIMITATIONS OF LIABILITY.
YOUR SOLE AND EXCLUSIVE REMEDY FOR ANY BREACH OF THE FOREGOING LIMITED WARRANTY SHALL BE, AT E-ICEBLUE'S OPTION, EITHER (A) REPAIR OR REPLACEMENT OF THE LICENSED SOFTWARE SO THAT IT CONFORMS TO THE FOREGOING LIMITED WARRANTY, OR (B) REFUND OF THE FEE THAT YOU PAID TO LICENSE THE LICENSED SOFTWARE.
IN NO EVENT SHALL E-ICEBLUE BE LIABLE FOR ANY DAMAGES OF ANY TYPE, WHETHER DIRECT OR INDIRECT, CONSEQUENTIAL, INCIDENTAL OR SPECIAL DAMAGES, INCLUDING WITHOUT LIMITATION, LOST REVENUES, LOST PROFITS, LOSSES RESULTING FROM BUSINESS INTERRUPTION OR LOSS OF DATA, REGARDLESS OF THE FORM OF ACTION OR LEGAL THEORY UNDER WHICH SUCH LIABILITY MAY BE ASSERTED, EVEN IF E-ICEBLUE HAS BEEN ADVISED OF THE POSSIBILITY OR LIKELIHOOD OF SUCH DAMAGES.
E-ICEBLUE SHALL HAVE NO LIABILITY WITH RESPECT TO ANY DATA THAT IS READ, ACCESSED, STORED OR PROCESSED WITH THE LICENSED SOFTWARE, OR FOR THE COSTS OF RECOVERING ANY SUCH DATA.
IN NO EVENT SHALL E-ICEBLUE'S MAXIMUM AGGREGATE LIABILITY UNDER THIS AGREEMENT EXCEED THE TOTAL FEES PAID OR PAYABLE BY YOU TO LICENSE THE LICENSED SOFTWARE.
SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OR EXCLUSION OF LIABILITY FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE ABOVE LIMITATION OR EXCLUSION MAY NOT APPLY TO YOU.
9. INDEMNIFICATION.
You agree to defend, indemnify, and hold E-iceblue and all of its employees, agents, representatives, directors, officers, partners, shareholders, attorneys, predecessors, successors, and assigns harmless from and against any and all claims, proceedings, damages, injuries, liabilities, losses, costs, and expenses (including reasonable attorneys' fees and litigation expenses), relating to or arising from Your use of the Licensed Software, or any breach of this Agreement, except to the extent such claim relates to or arises from a violation by e-iceblue of any third party copyright, trademark, trade secret or other intellectual property right.
10. EXPORT.
You agree that You will not export or transmit the Licensed Software or any Applications, directly or indirectly, to any restricted countries or in any manner that would violate United States laws and regulations as shall from time to time govern the license and delivery of technology abroad by persons subject to the jurisdiction of the United States government, including the Export Administration Act of 1979, as amended, and any applicable laws or regulations issued thereafter.
11. U.S. GOVERNMENT RESTRICTED RIGHTS.
If You are licensing the Licensed Software on behalf of the U.S. Government or any of its agencies ("Government"), the use, duplication, reproduction, release, modification, disclosure or transfer of the Licensed Software by the Government is subject to restricted rights in accordance with Federal Acquisition Regulation ("FAR") 12.212 for civilian agencies and Defense Federal Acquisition Regulation Supplement ("DFARS") 227.7202 for military agencies.
The Licensed Software is commercial. Use of the Licensed Software by the Government is further restricted in accordance with the terms and conditions of this Agreement.
12. MISCELLANEOUS.
If any provision of this Agreement is held to be invalid or unenforceable under any circumstances, its application in any other circumstances and the remaining provisions of this Agreement shall not be affected.
No waiver of any right under this Agreement shall be effective unless given in writing by an authorized representative of e-iceblue.
No waiver by e-iceblue of any right shall be deemed to be a waiver of any other right of e-iceblue arising under this Agreement.
This Agreement is solely between You and e-iceblue and shall not be construed to create any third party beneficiary rights in any other individual, partnership, corporation or other entity.
This Agreement shall be governed by and interpreted in accordance with the laws of the State of New York, without regard to its provisions governing conflicts of law.
Any and all disputes between You and e-iceblue pertaining to this Agreement shall be submitted to one arbitrator in binding arbitration within ten miles of New York City, New York in accordance with the Commercial Rules of the American Arbitration Association ("AAA").
The arbitrator shall be experienced in computer consulting, the development of custom software, the sale of packaged software, or related services.
If You and e-iceblue do not agree on an arbitrator within sixty (60) days of the institution of the arbitration, the arbitrator shall be chose by AAA.
Evidence and argument may be presented in person or by telephone, fax, postal mail, electronic mail, and other methods of communication approved by the arbitrator.
The prevailing party in such proceeding shall be entitled to recover its actually incurred costs, including reasonable attorney's fees, arbitration and court costs.
All hearings shall be held and a written arbitration award issued within one-hundred eighty (180) days of the date on which the arbitrator is appointed.
Judgment on the award shall be final and binding and may be entered in any court of competent jurisdiction.
13. ENTIRE AGREEMENT.
YOU AGREE THAT THIS AGREEMENT IS THE COMPLETE AND EXCLUSIVE STATEMENT OF THE AGREEMENT BETWEEN YOU AND E-ICEBLUE, AND THAT IT SUPERSEDES ANY PROPOSALS OR PRIOR AGREEMENTS, ORAL OR WRITTEN, AND ANY OTHER COMMUNICATIONS RELATING TO THE LICENSED SOFTWARE AND THE SUBJECT MATTER HEREOF.
E-ICEBLUE SHALL NOT BE BOUND BY ANY PROVISION OF ANY PURCHASE ORDER, RECEIPT, ACCEPTANCE, CONFIRMATION, CORRESPONDENCE OR OTHERWISE, OR BY ANY AGREEMENT BETWEEN YOU AND ANY OTHER PARTY, UNLESS E-ICEBLUE SPECIFICALLY AGREES TO SUCH PROVISION IN WRITING IN A FORM OF A LEGAL CONTRACT, DATED AND SIGNED BY YOU AND BY E-ICEBLUE'S OFFICER OR AUTHORIZED EMPLOYEE.
NO VENDOR, DISTRIBUTOR, PROVIDER, RESELLER, OEM, SALES REPRESENTATIVE, OR OTHER PERSON IS AUTHORIZED TO MODIFY THIS AGREEMENT OR TO MAKE ANY WARRANTY, REPRESENTATION OR PROMISE REGARDING THE LICENSED SOFTWARE WHICH IS DIFFERENT FROM THOSE SET FORTH IN THIS AGREEMENT.

92
Logger.cs Executable file
View File

@@ -0,0 +1,92 @@
namespace bdf
{
using System;
using System.Text;
internal static class Logger
{
public static void Log(uint level, string format, params object[] objs)
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("[{0}] ", DateTime.Now);
try
{
sb.AppendFormat(format, objs);
}
catch (Exception e)
{
Console.WriteLine("Logger: invalid parameters for formatting. {0}:{1}", e.Message, e.InnerException.Message);
}
if (level <= bdf.debug )
{
Console.WriteLine(sb.ToString());
bdf.outfile.WriteLine(sb.ToString());
}
if (level <= bdf.adlvl )
{
bdf.adminLog.AppendLine(sb.ToString());
}
}
/*
public static void Log(uint level, string format, string s1, string s2)
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("[{0}] ", DateTime.Now);
sb.AppendFormat(format, s1, s2);
if (level <= bdf.debug )
{
Console.WriteLine(sb.ToString());
bdf.outfile.WriteLine(sb.ToString());
}
if (level <= bdf.adlvl )
{
bdf.adminLog.AppendLine(sb.ToString());
}
}
public static void Log(uint level, string format, string s1)
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("[{0}] ", DateTime.Now);
sb.AppendFormat(format, s1);
if (level <= bdf.debug )
{
Console.WriteLine(sb.ToString());
bdf.outfile.WriteLine(sb.ToString());
}
if (level <= bdf.adlvl )
{
bdf.adminLog.AppendLine(sb.ToString());
}
}
public static void Log(uint level, string message)
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("[{0}] {1}", DateTime.Now, message);
if (level <= bdf.debug )
{
Console.WriteLine(sb.ToString());
bdf.outfile.WriteLine(sb.ToString());
}
if (level <= bdf.adlvl )
{
bdf.adminLog.AppendLine(sb.ToString());
}
}
*/
public static void Log(string message)
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("[{0}] {1}", DateTime.Now, message);
Console.WriteLine(sb.ToString());
bdf.outfile.WriteLine(sb.ToString());
bdf.adminLog.AppendLine(sb.ToString());
}
}
}

984
MegaT.cs Normal file
View File

@@ -0,0 +1,984 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Globalization;
using System.Reflection;
namespace bdf
{
public class MegaT
{
// SIP Extractions section
// A class to hold the extracted data for a single row of SIP INSIS data
public class SIPData
{
public string Item { get; set; }
public string Code { get; set; }
public string Description { get; set; }
public string Period { get; set; }
public string UnitPrice { get; set; }
public string Quantity { get; set; }
public string Amount { get; set; }
public string BillingType { get; set; }
public string Currency { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public override string ToString()
{
return $"Code: {Code}, Description: {Description}, Unit Price: {UnitPrice}, Qty: {Quantity}, Amount: {Amount}, Start Date: {StartDate}";
}
}
public static List<SIPData> GetSIPDetails_bySCHED(string sched, ref CookieContainer cookies)
{
bool success = false;
byte[] webResp = null;
List<SIPData> sip_rvnu = new List<SIPData> { };
success = Web.MakeRequest(
"GET",
"http://megatool.rogers.com/megatool/megatool/INSIS/insisMainwindow.asp?serv_id=" + sched,
false,
"",
ref webResp,
ref cookies);
if (!success)
{
Logger.Log(5, "Get SIP INSIS TopLevel Details FAIL {0}", sched);
}
string html = Encoding.ASCII.GetString(webResp);
if (html.Length > 5000) // valid SCHED, seek RVNU items for SIP data
{
try
{
Dictionary<string, string> rvnu = SIP_RVNU_items(html);
foreach (var kvp in rvnu)
{
success = false;
webResp = null;
success = Web.MakeRequest(
"GET",
"http://megatool.rogers.com/megatool/megatool/INSIS/" + kvp.Value.ToString(),
false,
"",
ref webResp,
ref cookies);
if (!success)
{
Logger.Log(5, "Get INSIS RVNU Details FAIL {0}-{1} {2}", sched, kvp.Key, webResp);
}
string html2 = Encoding.ASCII.GetString(webResp);
SIPData x = ExtractSIPData(html2);
sip_rvnu.Add(x);
Logger.Log(6, "Desc: {0} sip_rnvu size {1}", x.Description, sip_rvnu.Count);
}
}
catch (Exception e)
{
Logger.Log(0, "Error SCHED {0} - SIP HTML={0}", sched, e.Message);
}
}
return sip_rvnu;
}
public static Dictionary<string, string> SIP_RVNU_items(string html)
{
Dictionary<string, string> result = new System.Collections.Generic.Dictionary<string, string>( System.StringComparer.OrdinalIgnoreCase);
if (string.IsNullOrWhiteSpace(html))
return result;
string trPattern =
@"<tr[^>]*id\s*=\s*['""]R\d+['""][^>]*>(.*?)</tr>";
System.Text.RegularExpressions.MatchCollection trMatches =
System.Text.RegularExpressions.Regex.Matches(
html,
trPattern,
System.Text.RegularExpressions.RegexOptions.IgnoreCase |
System.Text.RegularExpressions.RegexOptions.Singleline
);
foreach (System.Text.RegularExpressions.Match trMatch in trMatches)
{
string trContent = trMatch.Groups[1].Value;
System.Text.RegularExpressions.MatchCollection tdMatches =
System.Text.RegularExpressions.Regex.Matches(
trContent,
@"<td[^>]*>(.*?)</td>",
System.Text.RegularExpressions.RegexOptions.IgnoreCase |
System.Text.RegularExpressions.RegexOptions.Singleline
);
if (tdMatches.Count < 5)
continue;
// ----- Extract Service Code (5th <td>) -----
string serviceCode =
System.Text.RegularExpressions.Regex.Replace(
tdMatches[4].Groups[1].Value,
"<[^>]+>",
string.Empty
).Trim();
if (serviceCode.Length == 0)
continue;
// Skip "Install" rows
if (serviceCode.IndexOf("Install", System.StringComparison.OrdinalIgnoreCase) >= 0)
{
//Console.WriteLine("skipping [{0}]", serviceCode);
continue;
}
// ----- Extract openIt('...') from 4th <td> -----
string fourthTd = tdMatches[3].Groups[1].Value;
//Console.WriteLine("4th [{0}]", fourthTd);
string openItValue = "";
if (fourthTd.IndexOf("RVNU", System.StringComparison.OrdinalIgnoreCase) >= 0)
{
System.Text.RegularExpressions.Match onclickMatch =
System.Text.RegularExpressions.Regex.Match(
fourthTd,
@"openIt\('(?<openit>[^']+)'\)",
System.Text.RegularExpressions.RegexOptions.IgnoreCase |
System.Text.RegularExpressions.RegexOptions.Singleline
);
if (!onclickMatch.Success)
{
//Console.WriteLine("no match");
continue;
}
openItValue = onclickMatch.Groups["openit"].Value.Trim();
}
else // Skip non-RVNU rows
{
//Console.WriteLine("non-revenue [{0}]", fourthTd);
continue;
}
// Avoid duplicate keys
if (!result.ContainsKey(serviceCode))
{
result.Add(serviceCode, openItValue);
}
}
return result;
}
public static SIPData ExtractSIPData(string html)
{
var extractedData = new SIPData();
// Regex to find table rows (<tr>) within a specific table structure (adjust if needed, e.g., using a table ID)
// The pattern uses capturing groups for each <td> content
// It assumes <td> tags might have extra spaces or attributes, but the content inside is the target.
Dictionary<string, string> result = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
if (string.IsNullOrWhiteSpace(html))
return null;
string pattern =
@"<td[^>]*class\s*=\s*""heading""[^>]*>\s*(?<heading>[^<]+)\s*</td>[\s\S]*?" +
@"value\s*=\s*""(?<value>[^""]*)""";
System.Text.RegularExpressions.MatchCollection matches =
System.Text.RegularExpressions.Regex.Matches(
html,
pattern,
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
foreach (System.Text.RegularExpressions.Match match in matches)
{
string heading = match.Groups["heading"].Value.Trim();
string value = match.Groups["value"].Value.Trim().Replace("$","").Replace("/", "-"); // FIXME convert to SSC style date
if (!result.ContainsKey(heading))
{
result.Add(heading.Replace(" ", ""), value); //Remove field label spaces to make them valid dictionary entries
Logger.Log(3, "Found: {0}={1}", heading, value);
}
}
System.Type type = typeof(SIPData);
foreach (System.Reflection.PropertyInfo prop in type.GetProperties(
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.Public))
{
//Console.WriteLine("a4n {0} : {1}", prop.PropertyType.Name, prop.Name);
if (prop.PropertyType != typeof(string))
continue;
if (!prop.CanWrite)
continue;
if (result.TryGetValue(prop.Name, out string value))
{
//Console.WriteLine("a5 {0}", value);
try
{
prop.SetValue( extractedData, (string)value);
}
catch (Exception e)
{
Logger.Log(0, "Error prop.SetValue {0}:{1}\n{2}", prop.Name, value, e.Message);
}
}
}
return extractedData;
}
public static string ConvertDate(string input)
{
System.DateTime date =
System.DateTime.ParseExact(
input,
"M-d-yyyy",
System.Globalization.CultureInfo.InvariantCulture
);
return date.ToString("yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture);
}
//------------------------------------
/*
public static Dictionary<string, string> ExtractServiceCodesFromTable(string html)
{
Dictionary<string, string> result = new Dictionary<string, string>();
if (string.IsNullOrWhiteSpace(html))
return result;
// Match each <tr> with id="R<number>", including multi-line content
string trPattern = @"<tr[^>]*id\s*=\s*['""]R\d+['""][^>]*>(.*?)</tr>";
var trMatches = Regex.Matches(
html,
trPattern,
RegexOptions.IgnoreCase | RegexOptions.Singleline // Singleline allows . to match newlines
);
foreach (Match trMatch in trMatches)
{
string trContent = trMatch.Groups[1].Value;
// Match all <td> elements inside the <tr>
var tdMatches = Regex.Matches(
trContent,
@"<td[^>]*>(.*?)</td>",
RegexOptions.IgnoreCase | RegexOptions.Singleline
);
if (tdMatches.Count >= 4)
{
string fourthTd = tdMatches[3].Groups[1].Value;
// Extract openIt('...') string inside the <a> tag
string onclickPattern = @"openIt\('(?<openit>[^']+)'\)";
var onclickMatch = Regex.Match(fourthTd, onclickPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
if (onclickMatch.Success)
{
string openItValue = onclickMatch.Groups["openit"].Value.Trim();
//result.Add(openItValue);
Console.WriteLine("Found {0}", openItValue);
}
}
}
return result;
}
/*
// Match each <tr> row
string rowPattern = @"<tr[^>]*id\s*=\s*['""]R\d+['""][^>]*>(.*?)</tr>";
MatchCollection rowMatches = Regex.Matches(html, rowPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
foreach (Match rowMatch in rowMatches)
{
string rowContent = rowMatch.Groups[1].Value;
Console.WriteLine("<TR> {0}", rowContent);
foreach (Match trMatch in rowContent)
{
string trContent = trMatch.Groups[1].Value;
Console.WriteLine("<TR> {0}", trContent);
// Match all <td> elements inside the <tr>
var tdMatches = Regex.Matches(
trContent,
@"<td[^>]*>(.*?)</td>",
RegexOptions.IgnoreCase | RegexOptions.Singleline
);
if (tdMatches.Count >= 4)
{
string fourthTd = tdMatches[3].Groups[1].Value;
// Extract openIt('...') string inside the <a> tag
string onclickPattern = @"openIt\('(?<openit>[^']+)'\)";
var onclickMatch = Regex.Match(fourthTd, onclickPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
if (onclickMatch.Success)
{
string openItValue = onclickMatch.Groups["openit"].Value.Trim();
result.Add(openItValue);
}
}
}
// Match <a ... onclick='...' ...> followed by <td> with service code
string cellPattern =
@"<a[^>]*onclick\s*=\s*['""][^'""]*'(?<onclick>[^']+)'[^'""]*['""][^>]*>.*?</a>.*?" +
@"<td[^>]*>\s*(?<code>[^<\s][^<]*)\s*</td>";
Match cellMatch = Regex.Match(rowContent, cellPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
if (cellMatch.Success)
{
string onclick = cellMatch.Groups["onclick"].Value.Trim();
string code = cellMatch.Groups["code"].Value.Trim();
if (!string.IsNullOrEmpty(code) && !string.IsNullOrEmpty(onclick))
{
// Avoid duplicate keys
if (!result.ContainsKey(code))
result[code] = onclick;
Console.WriteLine("Found {0} : {1}", code, onclick);
}
}
}
return result;
*/
// from Megatool RVNU sub-page, return extracted SIPData item
// old
public static List<SIPData> ExtractSIPData_RevScreen(string htmlContent)
{
var extractedData = new List<SIPData>();
// Regex to find table rows (<tr>) within a specific table structure (adjust if needed, e.g., using a table ID)
// The pattern uses capturing groups for each <td> content
// It assumes <td> tags might have extra spaces or attributes, but the content inside is the target.
string rowPattern = @"<tr\s*[^>]*?\bid=[^>]*?>(.*?)</tr\s*>"; //@"<tr\s*[^>]*>(.*?)</tr\s*>";
string cellPattern = @"<td\s*[^>]*>[$]*(.*?)</td>";
// Find all rows in the HTML
MatchCollection rows = Regex.Matches(htmlContent, rowPattern, RegexOptions.Singleline | RegexOptions.IgnoreCase);
foreach (Match rowMatch in rows)
{
string rowHtml = rowMatch.Groups[1].Value;
// Find all cells in the current row
MatchCollection cells = Regex.Matches(rowHtml, cellPattern, RegexOptions.Singleline | RegexOptions.IgnoreCase);
// Check if the row has exactly 9 columns of data (Item, Description, Unit Price, Qty, Amount)
if (cells.Count >= 9)
{
// Extract the inner text and clean up whitespace
string item = cells[0].Groups[1].Value.Replace("&nbsp;", " ").Trim();
string code = cells[1].Groups[1].Value.Replace("&nbsp;", " ").Trim();
string description = cells[2].Groups[1].Value.Replace("&nbsp;", " ").Trim();
string period = cells[3].Groups[1].Value.Replace("&nbsp;", " ").Trim();
string unitPrice = cells[4].Groups[1].Value.Replace("&nbsp;", " ").Trim();
string qty = cells[5].Groups[1].Value.Replace("&nbsp;", " ").Trim();
string amount = cells[6].Groups[1].Value.Replace("&nbsp;", " ").Trim();
string billingType = cells[7].Groups[1].Value.Replace("&nbsp;", " ").Trim();
string currency = cells[8].Groups[1].Value.Replace("&nbsp;", " ").Trim();
// Add to the list
extractedData.Add(new SIPData
{
Item = item,
Code = code,
Description = description,
Period = period,
UnitPrice = unitPrice,
Quantity = qty,
Amount = amount,
BillingType = billingType,
Currency = currency
});
}
}
return extractedData;
}
//old version
public static double getSIP_RVNU(string sched, ref CookieContainer cookies)
{
bool success = false;
double mrr = 0;
byte[] webResp = null;
success = Web.MakeRequest(
"GET",
"http://megatool.rogers.com/megatool/megatool/INSIS/insisMainwindow.asp?serv_id=" + sched,
false,
"",
ref webResp,
ref cookies);
if (!success)
{
Logger.Log(5, "MRR FAIL {0}", sched);
}
string html = Encoding.ASCII.GetString(webResp);
if (html.Length > 5000)
{
try
{
Regex word = new Regex(@"<tr\b[^>]*>[\s\S]*?Total\s+MRR[\s\S]*?\$\s*([0-9]{1,3}(?:,[0-9]{3})*(?:\.[0-9]{2})?)[\s\S]*?<\/tr>"); // find MRR dollar value
Match m = word.Match(html); //
if (m.Success)
{
Group g = m.Groups[1];
//Capture c = g.Captures[0];
Logger.Log(6, "Regex Match {0} / Group Count {1} / Captures Count {2} / result={3}", m.Success, m.Groups.Count, m.Captures.Count, g.Value);
mrr = Convert.ToDouble(g.Value);
if ((mrr >= 0) && (mrr <= 999999))
Logger.Log(5, "MRR found successfully {0}", mrr);
}
else
{
Logger.Log(1, "No MRR found.");
}
}
catch (Exception e)
{
Logger.Log(0, "Error parsing MRR {0}", e.Message);
}
}
return mrr;
}
// _RevScreen
public static List<SIPData> GetSIPDetails(string sched, ref CookieContainer cookies)
{
string token = "";
bool success = false;
byte[] webResp = null;
string html = "";
// http://megatool.rogers.com/megatool/megatool/INSIS/revenue.asp?logo=N&serv_id==
if (sched != "dummy")
{
success = Web.MakeRequest(
"GET",
"http://megatool.rogers.com/megatool/megatool/INSIS/revenue.asp?logo=N&serv_id=" + sched,
false,
"",
ref webResp,
ref cookies);
if (!success)
{
Logger.Log(0, "Get SIP details fail{0}", token);
}
//Console.WriteLine(Encoding.ASCII.GetString(webResp));
html = Encoding.ASCII.GetString(webResp);
}
else
{
success = true;
html = "";
}
List<SIPData> data = new List<SIPData> { };
// SIP details extraction
try
{
// data = ExtractSIPData(html);
SIPData junk = ExtractSIPData(html);
/*
foreach (var row in data)
{
//Console.WriteLine(row.ToString());
if ( row.Description.Contains("Access") ) Logger.Log(1,"Found Access: {0} x {1}", row.UnitPrice, row.Qty);
if ( row.Description.Contains("Session") ) Logger.Log(1, "Found Sessions: {0} x {1}", row.UnitPrice, row.Qty);
}
*/
}
catch (Exception e)
{
Logger.Log(0, "Exception: SIP Details {0}:{1}", e.Message, e.InnerException.Message);
}
return data; // no match found
}
//------------------------------------
// SCHED-A Info Extraction
public static Dictionary<string, string> GetParms(string sched, ref CookieContainer cookies)
{
string token = "";
bool success = false;
byte[] webResp = null;
string html = "";
Dictionary<string, string> parms = new Dictionary<string, string> { };
if (sched != "dummy")
{
success = Web.MakeRequest(
"GET",
"http://megatool.rogers.com/megatool/megatool/INSIS/schedule.asp?logo=N&serv_id=" + sched,
false,
"",
ref webResp,
ref cookies);
if (!success)
{
Logger.Log(0, "GetParms fail{0}", token);
}
//Console.WriteLine(Encoding.ASCII.GetString(webResp));
html = Encoding.ASCII.GetString(webResp);
}
else
{
success = true;
html = "";
}
try
{
// SO + up to 5 non-digits + six digits
var regex = new Regex(@"SO(?:\D{0,5})(\d{6})", RegexOptions.IgnoreCase);
Match m = regex.Match(html);
if (m.Success)
{
// m.Value = the entire match
parms.Add("SO", m.Groups[1].ToString()); // = the 6-digit number
}
else
{
parms.Add("SO", "XXX");
}
// TA + up to 5 non-digits + R + nine digits
regex = new Regex(@"TA(?:\D{0,5})(\d{9})", RegexOptions.IgnoreCase);
m = regex.Match(html);
if (m.Success)
{
// m.Value = the entire match
parms.Add("TA", "R"+m.Groups[1].ToString()); // = the 6-digit number
}
else
{
parms.Add("TA", "XXX");
}
// COP + up to 5 non-digits + six digits
regex = new Regex(@"COP(?:\D{0,5})(\d{6})", RegexOptions.IgnoreCase);
m = regex.Match(html);
if (m.Success)
{
// m.Value = the entire match
parms.Add("COP", m.Groups[1].ToString()); // = the 6-digit number
}
else
{
parms.Add("COP", "XXX");
}
// PRID + up to 5 non-digits + four digits
//regex = new Regex(@"PR.*ID(?:\D{0,5})(\d{4})", RegexOptions.IgnoreCase);
regex = new Regex(@"PR(?:\s?ID)?(?:\D{0,5})(\d{4})", RegexOptions.IgnoreCase);
m = regex.Match(html);
if (m.Success)
{
// m.Value = the entire match
parms.Add("PRID", m.Groups[1].ToString()); // = the 6-digit number
}
else
{
parms.Add("PRID", "XXX");
}
// Contract + up to 5 non-digits + letter + 9 digits
regex = new Regex(@"CONTRACT(?:\D{0,5})([a-zA-Z]\d{9})", RegexOptions.IgnoreCase);
m = regex.Match(html);
if (m.Success)
{
// m.Value = the entire match
parms.Add("CONTRACT", m.Groups[1].ToString()); // = the alpha+9-digit number
}
else
{
parms.Add("CONTRACT", "XXX");
}
//
parms.Add("SCHED", sched); // needed to build that datatable correctly in MAIN
//
// Billing Start Date; seems to come in Mon D, YYYY format, need to convert to YYYYMMDD
//regex = new Regex(@"<br>Bill Start Date:\s+([a-zA-Z0-9,\s]+[0-9]{4})[.]?\s*<br>", RegexOptions.IgnoreCase);
// Bill(?:ing|in)?\sStart(?: Date)?:\s
regex = new Regex(@"<br>Bill(?:ing|in)?\sStart(?: Date)?:\s+([a-zA-Z0-9,\s]+[0-9]{4})[.]?\s*<br>", RegexOptions.IgnoreCase);
m = regex.Match(html);
if (m.Success)
{
Logger.Log(5, "raw BSD = |{0}|", m.Groups[1].ToString());
try
{
// m.Value = the entire match
string input = m.Groups[1].ToString();
string iformat = "MMM d, yyyy";
string oformat = "yyyyMMdd";
DateTime fdate = DateTime.ParseExact(input, iformat, CultureInfo.InvariantCulture);
parms.Add("BSD", fdate.ToString(oformat)); // = the alpha+9-digit number
Logger.Log(4, "BSD = >{0}<", fdate.ToString(oformat));
}
catch (Exception e)
{
Logger.Log(0, "Error converting date from SchedA->Schedule details {0}", e.Message);
}
}
else
{
parms.Add("BSD", "XXX");
}
// MRR+ up to 5 non-digits + $XXX.XX
//regex = new Regex(@"(?<!Old\s)(?:New\s)?(?:MRR|MRC)[^0-9$]{0,5}\$?\s*([0-9,]+(?:\.\d{1,2})?)", RegexOptions.IgnoreCase);
regex = new Regex(@"(?<!Old\s)(?:New\s)?(?:MRR|MRC)[^0-9$]{0,5}\$?(\d+(?:\.\d{1,2})?)", RegexOptions.IgnoreCase);
m = regex.Match(html);
if (m.Success)
{
// m.Value = the entire match
string _mrr = m.Groups[1].ToString();
_mrr = Regex.Replace(_mrr, @"[^0-9.]", "");
parms.Add("MRR", _mrr); // = the alpha+9-digit number
}
else
{
parms.Add("MRR", "XXX");
}
// NRC+ up to 5 non-digits + $XXX.XX
regex = new Regex(@"(?:NRR|NRC)[^0-9$]{0,5}\$?\s*([0-9,]+(?:\.\d{1,2})?)", RegexOptions.IgnoreCase);
//regex = new Regex(@"(?<!Old\s)(?:New\s)?(?:NRR|NRC)[^0-9$]{0,5}\$?\s*([0-9,]+(?:\.\d{1,2})?)", RegexOptions.IgnoreCase);
m = regex.Match(html);
if (m.Success)
{
// m.Value = the entire match
try
{
string _nrc = m.Groups[1].ToString();
_nrc = Regex.Replace(_nrc, @"[^0-9.]", "");
parms.Add("NRC", String.Format( "{0:0.00}", _nrc)); // = decimal currency only
}
catch (Exception e)
{
Logger.Log(0, "NRC Parm: {0}:{1}", e.Message, e.InnerException.Message);
}
}
else
{
parms.Add("NRC", "XXX");
}
Logger.Log(2, "{0} : SO:{1} COP-{2} TA: {3} PRID: {4} Contract {5} BSD {6} MRR ${7} NRC ${8}", sched, parms["SO"], parms["COP"],
parms["TA"], parms["PRID"], parms["CONTRACT"], parms["BSD"], parms["MRR"], parms["NRC"] );
//Logger.Log(1, "SO:{0}", parms["SO"]);
}
catch (Exception e)
{
Logger.Log(0, "Exception: {0}:{1}", e.Message, e.InnerException.Message);
}
return parms; // no match found
}
// <tr\b[^>]*>[\s\S]*?MRR[\s\S]*?\$\s*(\d{1,3}(?:,\d{3})*(?:\.\d{2})?)[\s\S]*?</tr>
public static double getMRR(string sched, ref CookieContainer cookies)
{
bool success = false;
double mrr = 0;
byte[] webResp = null;
success = Web.MakeRequest(
"GET",
"http://megatool.rogers.com/megatool/megatool/INSIS/insisMainwindow.asp?serv_id=" + sched,
false,
"",
ref webResp,
ref cookies);
if (!success)
{
Logger.Log(5, "MRR FAIL {0}", sched);
}
string html = Encoding.ASCII.GetString(webResp);
if (html.Length > 5000)
{
try
{
Regex word = new Regex(@"<tr\b[^>]*>[\s\S]*?Total\s+MRR[\s\S]*?\$\s*([0-9]{1,3}(?:,[0-9]{3})*(?:\.[0-9]{2})?)[\s\S]*?<\/tr>"); // find MRR dollar value
Match m = word.Match(html); //
if (m.Success)
{
Group g = m.Groups[1];
//Capture c = g.Captures[0];
Logger.Log(6, "Regex Match {0} / Group Count {1} / Captures Count {2} / result={3}", m.Success, m.Groups.Count, m.Captures.Count, g.Value);
mrr = Convert.ToDouble(g.Value);
if ((mrr >= 0) && (mrr <= 999999))
Logger.Log(5, " {1} MRR found successfully {0}", mrr, sched);
}
else
{
Logger.Log(1, "No MRR found.");
}
}
catch (Exception e)
{
Logger.Log(0, "Error parsing MRR {0}", e.Message);
}
}
return mrr;
}
public static bool SchedXL(string sched, ref CookieContainer cookies)
{
string token = "";
bool success = false;
byte[] webResp = null;
success = Web.MakeRequest(
"GET",
"http://megatool.rogers.com/megatool/megatool/INSIS/insisMainwindow.asp?serv_id=" + sched,
false,
"",
ref webResp,
ref cookies);
if (!success)
{
Logger.Log(5, "Check Inactive SchedA's fail. {0}", token);
}
//Console.WriteLine(Encoding.ASCII.GetString(webResp));
else
{
string html = Encoding.ASCII.GetString(webResp);
if (html.Length < 5000) return true; // bit of a h*ck for when NSIS says 'no records'
const string startKey = ">Order Type (";
const string endKey = ")<br";
//var results = new List<string>();
int index = 0;
while (true)
{
// Find "serv_id="
int start = html.IndexOf(startKey, index, StringComparison.OrdinalIgnoreCase);
if (start == -1)
break; // no more matches
start += startKey.Length;
// Find "')"
int end = html.IndexOf(endKey, start, StringComparison.Ordinal);
if (end == -1)
break;
string value = html.Substring(start, end - start);
if ((value == "XL") || (value == "XP") || (value == "NX")) return true;
index = end + endKey.Length;
}
}
return false;
}
public static bool GetSchedAs(string serv_id, ref List<string> scheds, ref CookieContainer cookies)
{
bool success = false;
string token = "";
byte[] webResp = null;
success = Web.MakeRequest(
"POST",
"http://megatool.rogers.com/megatool/megatool/INSIS/SearchSites.asp?query=Y&exportFlag=N",
"service_id="+serv_id,
false,
"",
ref webResp,
ref cookies);
if (!success)
{
Logger.Log(0, "Get SchedA's Fail {0}", token);
}
//Console.WriteLine(Encoding.ASCII.GetString(webResp));
else
{
string html = Encoding.ASCII.GetString(webResp);
const string startKey = "serv_id=";
const string endKey = "')";
//var results = new List<string>();
int index = 0;
while (true)
{
// Find "serv_id="
int start = html.IndexOf(startKey, index, StringComparison.OrdinalIgnoreCase);
if (start == -1)
break; // no more matches
start += startKey.Length;
// Find "')"
int end = html.IndexOf(endKey, start, StringComparison.Ordinal);
if (end == -1)
break;
string value = html.Substring(start, end - start);
scheds.Add(value);
index = end + endKey.Length;
}
}
return success;
}
//perform NTLM authentication for MegaTool with users LAN ID
public static bool Auth(string user, string pass, ref CookieContainer cookies)
{
string url = "http://megatool.rogers.com/megatool/megatool/";
bool success = false;
// Explicit credentials (domain\user)
var creds = new NetworkCredential(user, pass, "RCI");
// A cookie container is REQUIRED to capture session cookies
// var cookies = new CookieContainer();
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.AllowAutoRedirect = false; // Required for NTLM handshake
request.PreAuthenticate = false; // NTLM cannot pre-authenticate
request.UseDefaultCredentials = false;
request.Credentials = creds; // Enables SSPI NTLM handshake
request.CookieContainer = cookies; // Store session cookies
request.KeepAlive = true; // NTLM requires same connection
request.UserAgent = "NTLMClient/.NET4.8";
Logger.Log(1, "Megatool NTLM authentication for ({0})...", user);
HttpWebResponse response;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException wex) when (wex.Response is HttpWebResponse)
{
response = (HttpWebResponse)wex.Response;
}
// If server demands NTLM, the framework automatically:
// • sends Type1
// • receives Type2
// • sends Type3
// • then returns the real authenticated page response
Logger.Log(5, "HTTP Status: " + (int)response.StatusCode + " " + response.StatusCode);
// Read response body
string body;
using (var reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
{
body = reader.ReadToEnd();
}
/*
Console.WriteLine("\n--- Page Content ---\n");
Console.WriteLine(body);
Console.WriteLine("\n--- Cookies Received ---");
*/
foreach (Cookie ck in cookies.GetCookies(request.RequestUri))
{
Logger.Log(5, $"{ck.Name} = {ck.Value}; Domain={ck.Domain}; Path={ck.Path}");
success = true;
}
response.Close();
return success;
}
}
}

383
PDF.cs Normal file
View File

@@ -0,0 +1,383 @@
using System;
using System.IO;
using System.Diagnostics;
using System.Collections.Generic;
using System.Globalization;
using Spire.Xls;
using System.Reflection;
namespace bdf
{
public class InvoiceCell // Invoice Cells from Invoice Template
{
public String Account { get; set; } = "I2"; // "Account"+ (also I32)
public String Date { get; set; } = "I3"; // I3 (also I33)
public String Invoice { get; set; } = "I4"; //I4 "Invoice" (also I34)
public String Total_Charges { get; set; } = "I14"; //I14 (also I36)
public String Account2 { get; set; } = "I32"; // "Account"+ (also I32)
public String Date2 { get; set; } = "I33"; // I3 (also I33)
public String Invoice2 { get; set; } = "I34"; //I4 "Invoice" (also I34)
public String Total_Charges2 { get; set; } = "I36"; //I14 (also I36)
public String CCI { get; set; } = "C12"; // C12 "Canada Contract Identifier"
public String PaperFee { get; set; } = "H17";
public String LateCharge { get; set; } = "H18";
public String Service_Charges { get; set; } = "I19";
public String UsageCharges { get; set; } = "H20";
public String TotalUsageCharges { get; set; } = "I21";
public String DataMonthlyCharges { get; set; } = "H23";
public String DataNon_RecurringCharges { get; set; } = "H24";
public String DataTotalOtherCharges { get; set; } = "H25";
public String Data_Services { get; set; } = "I27";
public String TaxON_PST { get; set; } = "F29";
public String TaxON_GST { get; set; } = "G29";
public String TaxON_HST { get; set; } = "H29";
public String TaxPQ_PST { get; set; } = "F30";
public String TaxPQ_GST { get; set; } = "G30";
public String TaxPQ_HST { get; set; } = "H30";
public String Taxes { get; set; } = "I31";
}
/*
// Source - https://stackoverflow.com/a
// Posted by Alexandru
// Retrieved 2025-12-03, License - CC BY-SA 3.0
internal class OutputSink : IDisposable
{
[DllImport("kernel32.dll")]
public static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll")]
public static extern int SetStdHandle(int nStdHandle, IntPtr hHandle);
private readonly TextWriter _oldOut;
private readonly TextWriter _oldError;
private readonly IntPtr _oldOutHandle;
private readonly IntPtr _oldErrorHandle;
public OutputSink()
{
_oldOutHandle = GetStdHandle(-11);
_oldErrorHandle = GetStdHandle(-12);
_oldOut = Console.Out;
_oldError = Console.Error;
Console.SetOut(TextWriter.Null);
Console.SetError(TextWriter.Null);
SetStdHandle(-11, IntPtr.Zero);
SetStdHandle(-12, IntPtr.Zero);
}
public void Dispose()
{
SetStdHandle(-11, _oldOutHandle);
SetStdHandle(-12, _oldErrorHandle);
Console.SetOut(_oldOut);
Console.SetError(_oldError);
}
}
*/
public class PDF
{
public static void Demo()
{
//MakePDF();
Dictionary<string, string> Invoice = new Dictionary<string, string> { };
InvoiceCell ic = new InvoiceCell { };
Invoice.Add(ic.Account, "Account P02-" + "123456"); //bdf2 C2
int d = 20250731;
Invoice.Add(ic.Date, dateFormal(d));
//string dt = "20250930";
Invoice.Add(ic.Invoice, ("Invoice " + d.ToString().Substring(4) + d.ToString().Substring(0, 4) + " - NU")); //mmddyyyy
Invoice.Add(ic.Total_Charges, String.Format("${0:n}", 10000));
Invoice.Add(ic.Account2, Invoice[ic.Account]);
Invoice.Add(ic.Date2, Invoice[ic.Date]);
Invoice.Add(ic.Invoice2, Invoice[ic.Invoice]);
Invoice.Add(ic.Total_Charges2, Invoice[ic.Total_Charges]);
customInvoice("doug", "", ref Invoice);
}
static void MakePDF()
{
// Create a Workbook object
Spire.Xls.Workbook workbook = new Spire.Xls.Workbook();
// Load an Excel file (replace with your file path)
workbook.LoadFromFile("test.xlsx");
//PdfFont fieldFont = new PdfFont(PdfFontFamily.Helvetica, 10f);
// Get the first worksheet
Spire.Xls.Worksheet sheet = workbook.Worksheets[0];
// Set the print area to a specific cell range
// Comment this line out if you need to export the entire worksheet as a PDF
//sheet.PageSetup.PrintArea = "B1:E6";
// Optional: Set worksheets to fit to page when converting
workbook.ConverterSetting.SheetFitToPage = true;
// Save the Excel file to PDF
workbook.SaveToFile("Output.pdf", FileFormat.PDF);
// Dispose resources
workbook.Dispose();
}
static void LoadStream()
{
// 1. Create a Workbook instance
Workbook workbook = new Workbook();
// 2. Create a Stream object (example using FileStream)
// Replace "sample.xls" with your actual file path or retrieve the stream from your source
FileStream fileStream = System.IO.File.OpenRead("sample.xls");
// Ensure the stream position is at the beginning (if necessary)
fileStream.Seek(0, SeekOrigin.Begin);
// 3. Use the Workbook.LoadFromStream() method to load the file
try
{
workbook.LoadFromStream(fileStream);
}
catch (Exception ex)
{
// Handle exceptions, e.g., file format not supported (Excel 95 or earlier not supported)
Logger.Log(0, "Error loading stream: {0}", ex.Message);
}
finally
{
// 4. Close the stream after loading
fileStream.Dispose();
}
// Now you can work with the workbook data
Worksheet sheet = workbook.Worksheets[0];
// ... do operations like reading cells, etc. ...
// Example of saving the processed file to a new file
workbook.SaveToFile("From_stream_processed.xls", ExcelVersion.Version97to2003);
Process.Start("From_stream_processed.xls");
}
static void LoadStreamXLSX()
{
// 1. Create a Workbook instance
Workbook workbook = new Workbook();
// 2. Open a FileStream from your source file
using (FileStream fileStream = System.IO.File.OpenRead("Sample.xlsx"))
{
// Ensure the stream position is at the beginning
fileStream.Seek(0, SeekOrigin.Begin);
// 3. Load the workbook from the stream
workbook.LoadFromStream(fileStream);
// 4. (Optional) Work with the workbook, e.g., modify a cell
workbook.Worksheets[0].Range["A1"].Text = "Data loaded from stream!";
// (Optional) Save the result to a new stream or file
// workbook.SaveToStream(outputStream);
// workbook.SaveToFile("Output.xlsx", ExcelVersion.Version2016);
}
}
public static Workbook LoadEmbeddedWorkbook(string resourceName)
{
// Get the assembly where the resource is stored
Assembly asm = Assembly.GetExecutingAssembly();
// Fully-qualified resource name (namespace + filename)
Stream stream = asm.GetManifestResourceStream(resourceName);
if (stream == null)
throw new Exception("Embedded resource not found: " + resourceName);
Workbook wb = new Workbook();
wb.LoadFromStream(stream); // FreeSpire.XLS supports this
stream.Close();
return wb;
}
public static void customInvoice(string type, string trace, ref Dictionary<string, string> CellData)
{
//string fontDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "");
string fontDirectory = AppDomain.CurrentDomain.BaseDirectory; // for non Windows systems use the .exe folder
//string fontDirectory2 = @"C:\\Windows\\Fonts\\";
//string[] fontDirectories = { fontDirectory, fontDirectory2 };
string[] fontDirectories = { fontDirectory };
/* Set the custom font file directory for the workbook instance
TextWriter originalOutput = Console.Out;
// Temporarily suppress console output
Console.SetOut(TextWriter.Null);
Workbook workbook = new Workbook(); // spews Not Implemented error
// Restore the original standard output writer
//Console.SetError(originalOutput);
//Console.SetOut(originalOutput);
/*
// Store the original listeners
var originalListeners = Debug.Listeners;
// Temporarily clear the listeners to suppress all Debug output
Debug.Listeners.Clear();
// Code here that generates unwanted debug output (e.g., a noisy library call)
Workbook workbook = new Workbook(); // spews Not Implemented error
// Re-add the original listeners (or just the DefaultTraceListener)
Debug.Listeners.Add(new DefaultTraceListener());
*/
Workbook workbook = new Workbook();
workbook = LoadEmbeddedWorkbook("BDF.Embedded.template.xlsx");
Logger.Log(" ...this will take a few seconds");
int dpi = 600;// image conversion resolution
workbook.ConverterSetting.XDpi = (dpi);
workbook.ConverterSetting.YDpi = (dpi);
workbook.ConverterSetting.JPEGQuality = 99;
//workbook.ConverterSetting.
// Create PdfSaveOptions instance
//PdfSaveOptions options = new Converter.PdfSaveOptions();
// Set a higher image resolution (e.g., 300 dpi for print quality)
//options.ImageResolution = 600; // You can experiment with values like 144, 220, or 300
// Save to PDF using the options
//workbook.SaveToFile("output_high_quality.pdf", options);
/*
using (new OutputSink())
{
Console.WriteLine("a");
workbook = new Workbook(); // spews Not Implemented error
Console.WriteLine("b");
}
*/
workbook.CustomFontFileDirectory = fontDirectories;
/* 1. Create a Workbook instance
//Workbook workbook = new Workbook();
// 2. Open a FileStream from your source file
using (FileStream fileStream = System.IO.File.OpenRead("template.xlsx")) //FIXME add checking
{
// Ensure the stream position is at the beginning
fileStream.Seek(0, SeekOrigin.Begin);
// 3. Load the workbook from the stream
workbook.LoadFromStream(fileStream);
*/
{
// 4. (Optional) Work with the workbook, e.g., modify a cell
foreach (var cell in CellData)
{
// workbook.Worksheets[0].Range["A1"].Text = "Data loaded from stream!";
workbook.Worksheets[0].Range[cell.Key].Text = cell.Value;
} // end foreach
//Spire.Xls.Worksheet sheet = workbook.Worksheets[0];
// Set the print area to a specific cell range
// Comment this line out if you need to export the entire worksheet as a PDF
//sheet.PageSetup.PrintArea = "B1:E6";
// Optional: Set worksheets to fit to page when converting
workbook.ConverterSetting.SheetFitToPage = true;
// (Optional) Save the result to a new stream or file
// workbook.SaveToStream(outputStream);
// workbook.SaveToFile("Output.xlsx", ExcelVersion.Version2016);
// Save the Excel file to PDF
// string pdf_name = "Output_" + type + ".pdf";
InvoiceCell ic = new InvoiceCell { };
string prefix = CellData[ic.Invoice].Substring(0, 16).Replace(' ', '_') + "_";
string pdf_name = prefix + type.ToUpper() + trace + ".pdf";
workbook.SaveToFile(pdf_name, FileFormat.PDF);
Logger.Log(0, "PDF written! ({0})", pdf_name);
} //end using
}
public static string dateFormal(int dateInt)
{
//int dateInt = 20251130;
string dateString = dateInt.ToString();
// 1. Define the input format ("yyyyMMdd")
string inputFormat = "yyyyMMdd";
// 2. Parse the string into a DateTime object
DateTime dateTimeObject = DateTime.ParseExact(
dateString,
inputFormat,
CultureInfo.InvariantCulture
);
// 3. Define the desired output format ("MMMM dd, yyyy")
// MMMM = Full month name
// dd = Day of the month
// yyyy = Year
string outputFormat = "MMMM d, yyyy";
string result = dateTimeObject.ToString(outputFormat);
//Console.WriteLine(result);
// Output: November 30, 2025
return result;
}
}
/*
// Ensure these files are present in this directory in your application's deployment environment.
string fontDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Fonts");
string[] fontDirectories = { fontDirectory };
// Set the custom font file directory for the workbook instance
Workbook workbook = new Workbook();
workbook.CustomFontFileDirectory = fontDirectories; //
// Load your Excel file
workbook.LoadFromFile("InputFile.xls");
// ... perform other operations ...
// When saving or converting (e.g., to PDF), the library will check the specified path for fonts
workbook.SaveToFile("OutputFile.xlsx", ExcelVersion.Version2013);
*/
}

31
Properties/AssemblyInfo.cs Executable file
View File

@@ -0,0 +1,31 @@
#region Using directives
using System;
using System.Reflection;
using System.Runtime.InteropServices;
#endregion
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("BDF")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Sommet Consulting Inc.")]
[assembly: AssemblyProduct("Billing Detail File")]
[assembly: AssemblyCopyright("Copyright 2025")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// This sets the default COM visibility of types in the assembly to invisible.
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
[assembly: ComVisible(false)]
// The assembly version has following format :
//
// Major.Minor.Build.Revision
//
// You can specify all the values or you can use the default the Revision and
// Build Numbers by using the '*' as shown below:
[assembly: AssemblyVersion("2.0.*")]

BIN
ROGERS_SIP_SO_124135_VER_0.xls Executable file

Binary file not shown.

801
SFTP.cs Normal file
View File

@@ -0,0 +1,801 @@
using System;
using System.IO;
using System.Reflection;
using System.Collections.Generic;
using System.Threading;
using Renci.SshNet;
using System.Linq;
namespace bdf
{
public class sftp
{
public class ConnectionDetails
{
public Int32 maxAttempts = 5;
public Int32 timeOutSecs = 30;
public Int32 retrySecs = 5;
public Int32 OperationTimeout = 30;
public Int32 KeepAliveInterval = 15;
public string ppkFile = "";
public string passPhrase = "";
public string username = "";
public string password = "";
public string host = "";
public Int32 port = 22;
}
public static Renci.SshNet.ConnectionInfo BuildConnectionInfo(ConnectionDetails cd)
{
var auth = new System.Collections.Generic.List<Renci.SshNet.AuthenticationMethod>();
PrivateKeyFile pkFile = null;
if (cd.username != "" && cd.ppkFile != "")
{
if (cd.ppkFile.Contains("Embedded"))
{
Logger.Log(1, " Processing internal PPK");
// Get the assembly where the resource is stored
Assembly asm = Assembly.GetExecutingAssembly();
Stream stream = Stream.Null;
if (asm.GetManifestResourceNames().Contains(cd.ppkFile))
// Fully-qualified resource name (namespace + filename)
stream = asm.GetManifestResourceStream(cd.ppkFile);
else
{
Logger.Log(0, "EXCEPTION: PPK resource not found.");
throw new Exception("Private key file not found. ");
}
//Console.WriteLine("b - {0} {1}", cd.ppkFile, stream == null);
try
{
if (stream == null || !stream.CanRead)
throw new Exception("Private key file not found/not readable. ");
else
stream.Position = 0; // reset stream position
}
catch (Exception e)
{
Logger.Log(3, "EXCEPTION PPK {0}:{1}", e.Message, e.InnerException.Message);
}
try
{
pkFile =
string.IsNullOrEmpty(cd.passPhrase)
? new PrivateKeyFile(stream)
: new PrivateKeyFile(stream, cd.passPhrase);
}
catch (Renci.SshNet.Common.SshException e)
{
throw new Exception("Problems with your internal private key and/or passphrase. " + e.Message);
}
stream.Close();
Logger.Log(5, " Internal PPK loaded");
}
else
{
try
{
pkFile =
string.IsNullOrEmpty(cd.passPhrase)
? new PrivateKeyFile(cd.ppkFile)
: new PrivateKeyFile(cd.ppkFile, cd.passPhrase);
}
catch (Renci.SshNet.Common.SshException e)
{
throw new Exception("Problems with your private key and/or passphrase. " + e.Message);
}
}
if (pkFile != null)
{
auth.Add(new Renci.SshNet.PrivateKeyAuthenticationMethod(cd.username, pkFile)); //preferred
Logger.Log(0, " Added PPK method.");
}
}
if (!string.IsNullOrEmpty(cd.password))
{
var kb = new Renci.SshNet.KeyboardInteractiveAuthenticationMethod(cd.username);
kb.AuthenticationPrompt += (s, e) =>
{
foreach (var p in e.Prompts)
p.Response = cd.password;
};
auth.Add(kb);
auth.Add(new Renci.SshNet.PasswordAuthenticationMethod(cd.username, cd.password));
Logger.Log(0, " Added user/pass method.");
}
return new Renci.SshNet.ConnectionInfo(cd.host, cd.port, cd.username, auth.ToArray())
{
Timeout = System.TimeSpan.FromSeconds(30),
RetryAttempts = 1
};
}
public static Renci.SshNet.SftpClient TrySftpConnectWithHardTimeout(
Renci.SshNet.ConnectionInfo connectionInfo,
int maxAttempts,
int timeoutSeconds)
{
for (int i = 0; i < maxAttempts; i++)
{
Renci.SshNet.SftpClient client = null;
try
{
var task = System.Threading.Tasks.Task.Run(() =>
{
client = new Renci.SshNet.SftpClient(connectionInfo);
// These are still useful, but not sufficient alone
client.ConnectionInfo.Timeout =
System.TimeSpan.FromSeconds(30);
client.KeepAliveInterval =
System.TimeSpan.FromSeconds(15);
client.Connect();
});
bool completed =
task.Wait(System.TimeSpan.FromSeconds(timeoutSeconds));
if (!completed)
{
// HARD TIMEOUT
try
{
client?.Dispose();
}
catch { }
//return null;
}
else
{
return client;
}
}
catch
{
try
{
client?.Dispose();
}
catch { }
//return null;
}
System.Threading.Thread.Sleep(5000);
}
return null;
}
public static bool serverExists(string host)
{
try
{
// 1. DNS resolution
System.Net.IPAddress[] addresses =
System.Net.Dns.GetHostAddresses(host);
if (addresses == null || addresses.Length == 0)
return false;
// 2. Ping first resolved address
using (System.Net.NetworkInformation.Ping ping =
new System.Net.NetworkInformation.Ping())
{
Logger.Log(1, "Validating server: {0} at {1}", host, addresses[0]);
System.Net.NetworkInformation.PingReply reply =
ping.Send(addresses[0], 3000); // 3s timeout
return reply != null &&
reply.Status ==
System.Net.NetworkInformation.IPStatus.Success;
}
}
catch
{
return false;
}
}
public static void Upload_Stream(MemoryStream ms, string filename, ConnectionDetails cd)
{
try
{
//using (var sftpClient = CreateClient(host, port, username, password))
var sftpInfo = BuildConnectionInfo(cd);
Renci.SshNet.SftpClient sftpClient = null;
try
{
sftpClient = TrySftpConnectWithHardTimeout(sftpInfo, cd.maxAttempts, cd.retrySecs);
}
catch (Renci.SshNet.Common.SshConnectionException e)
{
Logger.Log(1, " connection exception ({0}) : {1}", "", e.Message);
}
if (sftpClient == null)
{
Logger.Log(1, " null connection exception. Transfer failed.");
return;
}
try
{
sftpClient.UploadFile(
ms,
filename,
uploaded =>
{
Logger.Log(5, $"Uploaded {(double)uploaded / ms.Length * 100}% of the file.");
});
}
catch (Renci.SshNet.Common.SshException e)
{
Logger.Log(0, " SSH upload Exception {0}:{1}", e.Message, e.InnerException.Message);
}
Logger.Log(1, " -- uploaded: {0} ({3}KB) to {1}:{2}", filename, cd.host, cd.port, (ms.Length / 1024)+1);
//Console.WriteLine("starting dir pull");
var files = sftpClient.ListDirectory(".").Where(f => f.IsRegularFile &&
(f.Name.EndsWith(".ttf", System.StringComparison.OrdinalIgnoreCase) || //pdf
f.Name.EndsWith(".xlsx", System.StringComparison.OrdinalIgnoreCase)));
foreach (var s in files)
{
Logger.Log(0, " => {0} {1}", s.FullName, s.Attributes);
}
sftpClient.Disconnect();
Logger.Log(" SSH Disconnected");
try
{
sftpClient?.Dispose();
}
catch { }
return; // success
}
catch (Exception e)
{
Logger.Log(0, "SFTP exception {0}:{1}", e.Message, e.InnerException.Message);
}
}
// Legacy modules
/*
public static void Upload_Stream_old(MemoryStream ms, string outfile, ConnectionDetails cd)
{
//Logger.Log(0, "usp: file={0} host={1}:{2} user={3} pass={4}", outfile, cd.host, cd.port, cd.username, cd.password);
int attempts = 0;
while (true)
{
try
{
var valid_methods = new List<AuthenticationMethod>();
PrivateKeyFile keyFile;
if (cd.username != "" && cd.ppkFile != "")
{
if (cd.ppkFile.StartsWith("BDF"))
{
Logger.Log(3, "Processing PPK");
// Add in loading the private.key from an embedded resource file
// Get the assembly where the resource is stored
Assembly asm = Assembly.GetExecutingAssembly();
// Fully-qualified resource name (namespace + filename)
Stream stream = asm.GetManifestResourceStream(cd.ppkFile);
if (stream == null || !stream.CanRead)
throw new Exception("Private key file not found. ");
else
stream.Position = 0; // reset stream position
try
{
keyFile =
string.IsNullOrEmpty(cd.passPhrase)
? new PrivateKeyFile(stream)
: new PrivateKeyFile(stream, cd.passPhrase);
}
catch (Renci.SshNet.Common.SshException e)
{
throw new Exception("Problems with your internal private key and/or passphrase. " + e.Message);
}
stream.Close();
}
else
{
try
{
keyFile =
string.IsNullOrEmpty(cd.passPhrase)
? new PrivateKeyFile(cd.ppkFile)
: new PrivateKeyFile(cd.ppkFile, cd.passPhrase);Console.WriteLine("b");
}
catch (Renci.SshNet.Common.SshException e)
{
throw new Exception("Problems with your private key and/or passphrase. " + e.Message);
}
}
valid_methods.Add(new PrivateKeyAuthenticationMethod(cd.username, keyFile)); //preferred
}
if (cd.username != "" && cd.password != "")
{
valid_methods.Add(new PasswordAuthenticationMethod(cd.username, cd.password)); //fallback to user/pass
}
if (valid_methods.Count == 0)
throw new Exception("No valid login credentials found.");
Logger.Log(0, " Found {0} valid methods. Using method={1}", valid_methods.Count, valid_methods[0].Name);
AuthenticationMethod[] methods = valid_methods.ToArray();
ConnectionInfo connectionInfo =
new ConnectionInfo(
cd.host,
cd.port,
cd.username,
methods ) //fallback to user/pass
{
Timeout = System.TimeSpan.FromSeconds(cd.timeOutSecs)
};
//Console.WriteLine("Connection info done:");
using (var sftpClient = new SftpClient(connectionInfo))
{
//sftpClient.ConnectionInfo.Timeout = System.TimeSpan.FromSeconds(15); //set above in connectionInfo
sftpClient.OperationTimeout = System.TimeSpan.FromSeconds(cd.OperationTimeout);
sftpClient.KeepAliveInterval = System.TimeSpan.FromSeconds(cd.KeepAliveInterval);
attempts++;
try
{
Logger.Log(5, "trying connect {0}", sftpClient.ConnectionInfo.Username);
sftpClient.Connect();
}
catch (Renci.SshNet.Common.SshAuthenticationException e)
{
Logger.Log(1, " authentication exception ({0}) : {1}", attempts, e.Message);
}
catch (Renci.SshNet.Common.SshConnectionException e)
{
Logger.Log(1, " connection exception ({0}) : {1}", attempts, e.Message);
}
catch (Exception e)
{
Logger.Log(1, " connection exception ({0}) : {1}", attempts, e.Message);
}
//------------
if (!sftpClient.IsConnected)
{
Logger.Log(1, " connection failure {0}", attempts);
if (attempts < 10) { Thread.Sleep(TimeSpan.FromSeconds(5)); continue; } else { break; };
}
try
{
sftpClient.UploadFile(
ms,
outfile,
uploaded =>
{
Logger.Log(5, $"Uploaded {(double)uploaded / ms.Length * 100}% of the file.");
});
}
catch (Renci.SshNet.Common.SshException e)
{
Logger.Log(0, " SSH upload Exception {0}:{1}", e.Message, e.InnerException.Message);
}
Logger.Log(1, " -- uploaded: {0} ({3}KB) to {1}:{2}", outfile, cd.host, cd.port, ((ms.Length / 1024) + 1));
//Console.WriteLine("starting dir pull");
var files = sftpClient.ListDirectory(".").Where(f => f.IsRegularFile &&
( f.Name.EndsWith(".ttf", System.StringComparison.OrdinalIgnoreCase) || //pdf
f.Name.EndsWith(".xlsx", System.StringComparison.OrdinalIgnoreCase) ) );
foreach (var s in files)
{
Logger.Log(0, " => {0} {1}", s.FullName, s.Attributes);
}
//if (client.Exists(path))
//{
// client.DeleteFile(path);
//}
sftpClient.Disconnect();
Logger.Log(" SSH Disconnected");
return; // success
}
}
catch (Exception e)
{
Logger.Log(0, "SFTP exception {0}:{1}", e.Message, e.InnerException.Message);
}
attempts++;
if (attempts >= cd.maxAttempts)
{
Logger.Log(0, ("Failed to Connect after 10 attempts."));
return;
}
Logger.Log(1, " ...retrying ({0})", attempts);
Thread.Sleep(TimeSpan.FromSeconds(5));
} // end of while true/do forever
}
public static void Upload_stream_dev(MemoryStream ms, string filename)
{
int attempts = 0;
int maxAttempts = 5;
int timeOut = 30; //seconds
string ppkFile = "BDF.Embedded.private_passphr.ppk";
//passPhrase = "";
string passPhrase = "Rogers1!";
string username = "DEV_APP_BDF";
string host = "dev.mft.rogers.com";
int port = 22;
Logger.Log(5, "usp: file={0} host={1}:{2} user={3} pass={4}", filename, host, port, username, passPhrase);
while (true)
{
try
{
// Add in loading the private.key from an embedded resource file
// Get the assembly where the resource is stored
Assembly asm = Assembly.GetExecutingAssembly();
// Fully-qualified resource name (namespace + filename)
Stream stream = asm.GetManifestResourceStream(ppkFile);
//Stream stream = asm.GetManifestResourceStream("BDF.Embedded.private_nopassphr.ppk");
if (stream == null || !stream.CanRead)
throw new Exception("Private keys not found. ");
PrivateKeyFile keyFile =
string.IsNullOrEmpty(passPhrase)
? new PrivateKeyFile(stream)
: new PrivateKeyFile(stream, passPhrase);
stream.Close();
ConnectionInfo connectionInfo =
new ConnectionInfo(
host,
port,
username,
new PrivateKeyAuthenticationMethod(username, keyFile))
{
Timeout = System.TimeSpan.FromSeconds(timeOut)
};
//Console.WriteLine("Connection info done:");
using (var sftpClient = new SftpClient(connectionInfo))
{
sftpClient.ConnectionInfo.Timeout = System.TimeSpan.FromSeconds(15);
sftpClient.OperationTimeout = System.TimeSpan.FromSeconds(30);
sftpClient.KeepAliveInterval = System.TimeSpan.FromSeconds(10);
attempts++;
try
{
Logger.Log(5, "trying connect {0}", sftpClient.ConnectionInfo.Username);
sftpClient.Connect();
}
catch (Renci.SshNet.Common.SshConnectionException e)
{
Logger.Log(1, " connection exception ({0}) : {1}", attempts, e.Message);
}
//------------
if (!sftpClient.IsConnected)
{
Logger.Log(1, " connection failure {0}", attempts);
if (attempts < 10) { Thread.Sleep(TimeSpan.FromSeconds(5)); continue; } else { break; };
}
try
{
sftpClient.UploadFile(
ms,
filename,
uploaded =>
{
Logger.Log(5, $"Uploaded {(double)uploaded / ms.Length * 100}% of the file.");
});
}
catch (Renci.SshNet.Common.SshException e)
{
Logger.Log(0, " SSH upload Exception {0}:{1}", e.Message, e.InnerException.Message);
}
Logger.Log(1, " -- uploaded: {0} ({3}KB) to {1}:{2}", filename, host, port, ((ms.Length / 1024)+1));
//Console.WriteLine("starting dir pull");
var files = sftpClient.ListDirectory(".").Where(f => f.IsRegularFile &&
f.Name.EndsWith(".ttf", System.StringComparison.OrdinalIgnoreCase));
foreach (var s in files)
{
Logger.Log(0, " => {0} {1}", s.FullName, s.Attributes);
}
//if (client.Exists(path))
//{
// client.DeleteFile(path);
//}
sftpClient.Disconnect();
Logger.Log(" SSH Disconnected");
return; // success
}
}
catch (Exception e)
{
Logger.Log(0, "SFTP exception {0}:{1}", e.Message, e.InnerException.Message);
}
attempts++;
if (attempts >= maxAttempts)
{
Logger.Log(0, ("Failed to Connect after 10 attempts."));
return;
}
Logger.Log(1, " ...retrying ({0})", attempts);
Thread.Sleep(TimeSpan.FromSeconds(5));
} // end of while true/do forever
}
public static void Upload_stream_ppk(MemoryStream ms, string filename, string host, int port, string username)
{
int attempts = 0;
int maxAttempts = 5;
int timeOut = 30; //seconds
string passPhrase = "Rogers1!";
//passPhrase = "";
//string username = "DEV_APP_BDF";
//string host = "dev.mft.rogers.com";
//int port = 22;
Logger.Log(5,"usp: file={0} host={1}:{2} user={3} pass={4}", filename, host, port, username, passPhrase);
while (true)
{
try
{
// Add in loading the private.key from an embedded resource file
// Get the assembly where the resource is stored
Assembly asm = Assembly.GetExecutingAssembly();
// Fully-qualified resource name (namespace + filename)
Stream stream = asm.GetManifestResourceStream("BDF.Embedded.private_passphr.ppk");
//Stream stream = asm.GetManifestResourceStream("BDF.Embedded.private_nopassphr.ppk");
if (stream == null || !stream.CanRead)
throw new Exception("Private keys not found. ");
PrivateKeyFile keyFile =
string.IsNullOrEmpty(passPhrase)
? new PrivateKeyFile(stream)
: new PrivateKeyFile(stream, passPhrase);
stream.Close();
ConnectionInfo connectionInfo =
new ConnectionInfo(
host,
port,
username,
new PrivateKeyAuthenticationMethod(username, keyFile))
{
Timeout = System.TimeSpan.FromSeconds(timeOut)
};
//Console.WriteLine("Connection info done:");
using (var sftpClient = new SftpClient(connectionInfo))
{
sftpClient.ConnectionInfo.Timeout = System.TimeSpan.FromSeconds(15);
sftpClient.OperationTimeout = System.TimeSpan.FromSeconds(30);
sftpClient.KeepAliveInterval = System.TimeSpan.FromSeconds(10);
attempts++;
try
{
Logger.Log(5,"trying connect {0}", sftpClient.ConnectionInfo.Username);
sftpClient.Connect();
}
catch (Renci.SshNet.Common.SshConnectionException e)
{
Logger.Log(1, " connection exception ({0}) : {1}", attempts, e.Message);
}
//------------
if (!sftpClient.IsConnected)
{
Logger.Log(1, " connection failure {0}", attempts);
if (attempts < 10) { Thread.Sleep(TimeSpan.FromSeconds(5)); continue; } else { break; };
}
try
{
Console.WriteLine("trying to upload");
sftpClient.UploadFile(
ms,
filename,
uploaded =>
{
Logger.Log(5, $"Uploaded {(double)uploaded / ms.Length * 100}% of the file.");
});
}
catch (Renci.SshNet.Common.SshException e)
{
Logger.Log(0, " SSH upload Exception {0}:{1}", e.Message, e.InnerException.Message);
}
Logger.Log(1, " -- uploaded: {0} ({3}KB) to {1}:{2}", filename, host, port, (ms.Length / 1024));
Console.WriteLine("starting dir pull");
var files = sftpClient.ListDirectory(".");
foreach(var s in files)
{
Console.WriteLine("* {0}", s.FullName);
}
Console.WriteLine("disconnecting");
sftpClient.Disconnect();
Logger.Log(" SSH Disconnected");
return; // success
}
}
catch (Exception e)
{
Logger.Log(0, "SFTP exception {0}:{1}", e.Message, e.InnerException.Message);
}
attempts++;
if (attempts >= maxAttempts)
{
Logger.Log(0, ("Failed to Connect after 10 attempts."));
return;
}
Logger.Log(1, " ...retrying ({0})", attempts);
Thread.Sleep(TimeSpan.FromSeconds(5));
} // end of while true/do forever
}
public static void Upload_stream_old( MemoryStream ms, string filename, string host, int port, string username, string password)
{
try
{
using (var sftpClient = new SftpClient(host, port, username, password))
//using (var fs = new FileStream(fileToUpload, FileMode.Open))
{
sftpClient.OperationTimeout = TimeSpan.FromSeconds(30);
sftpClient.ConnectionInfo.Timeout = TimeSpan.FromSeconds(30);
int attempts = 0;
do
{
attempts++;
try
{
sftpClient.Connect();
}
catch (Renci.SshNet.Common.SshConnectionException e)
{
Logger.Log(1," retrying ({0}) : {1}",attempts, e.Message);
Thread.Sleep(TimeSpan.FromSeconds(5));
}
}
while (attempts < 10 && !sftpClient.IsConnected);
if (attempts >= 10)
{
throw new Exception("Failed to Connect after 10 attempts.");
}
else
{
Logger.Log(" SSH Connected");
try
{
sftpClient.UploadFile(
ms,
filename,
uploaded =>
{
Logger.Log(5, $"Uploaded {(double)uploaded / ms.Length * 100}% of the file.");
});
}
catch (Renci.SshNet.Common.SshException e)
{
Logger.Log(0, " SSH upload Exception {0}:{1}", e.Message, e.InnerException.Message);
}
Logger.Log(" SSH Disconnected");
sftpClient.Disconnect();
}
}
Logger.Log(1, " -- uploaded: {0} ({3}KB) to {1}:{2}", filename, host, port, ( ms.Length/1024) );
}
catch (Exception e)
{
Logger.Log(e.Message);
}
}
public static void Upload_file(string fileToUpload, string host, int port, string username, string password)
{
try
{
using (var sftpClient = new SftpClient(host, port, username, password))
using (var fs = new FileStream(fileToUpload, FileMode.Open))
{
sftpClient.OperationTimeout = TimeSpan.FromSeconds(30);
int attempts = 0;
do
{
try
{
attempts += 1;
sftpClient.Connect();
}
catch (Renci.SshNet.Common.SshConnectionException e)
{
Logger.Log(1, " retrying in 5s ({0}) : {1}", attempts, e.Message);
Thread.Sleep(TimeSpan.FromSeconds(5));
}
} while (attempts < 10 && !sftpClient.IsConnected);
Logger.Log(" SSH Connected");
try
{
sftpClient.UploadFile(
fs,
"/Doug/" + Path.GetFileName(fileToUpload),
uploaded =>
{
Logger.Log(5,$"Uploaded {(double)uploaded / fs.Length * 100}% of the file.");
});
}
catch (Renci.SshNet.Common.SshException e)
{
Logger.Log(0, " SSH Exception {0}:{1}", e.Message, e.InnerException.Message);
}
sftpClient.Disconnect();
}
Logger.Log(1," uploaded: {0}", fileToUpload);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
*/
}
}

BIN
Spire.Pdf.dll Executable file

Binary file not shown.

BIN
Spire.XLS.dll Executable file

Binary file not shown.

468
Web.cs Normal file
View File

@@ -0,0 +1,468 @@
/*
* Created by SharpDevelop.
* User: dmacinto
* Date: 10/05/11
* Time: 3:04 PM
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using System.Net;
using System.IO;
using System.Text;
//using System.Configuration;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
namespace bdf
{
/// <summary>
/// Provides wrapper around HttpWebRequest, handling 302 redir, binary and certificate issues
/// </summary>
public class Web
{
public Web()
{
}
//Login1 (used to acquire token for auth)
public static bool MakeRequest(string method, string uri, bool json, ref string token, ref byte[] webdata, ref CookieContainer cookie)
{
bool redir = true;
string vars = "";
//string token = bdf.token;
WebProxy proxy = null;
return MakeByteRequest(method, redir, uri, vars, ref webdata, json, ref token, ref cookie, proxy);
}
// as above but with RO token option
public static bool MakeRequest(string method, string uri, bool json, string token, ref byte[] webdata, ref CookieContainer cookie)
{
bool redir = true;
string vars = "";
WebProxy proxy = null;
return MakeByteRequest(method, redir, uri, vars, ref webdata, json, ref token, ref cookie, proxy);
}
//Login2
public static bool MakeRequest(string method, string uri, string vars, bool json, ref byte[] webdata, ref CookieContainer cookie)
{
bool redir = true;
string token = bdf.token;
WebProxy proxy = null;
return MakeByteRequest(method, redir, uri, vars, ref webdata, json, ref token, ref cookie, proxy);
}
//as above with RO token
public static bool MakeRequest(string method, string uri, string vars, bool json, string token, ref byte[] webdata, ref CookieContainer cookie)
{
bool redir = true;
WebProxy proxy = null;
return MakeByteRequest(method, redir, uri, vars, ref webdata, json, ref token, ref cookie, proxy);
}
/* public static bool MakeRequest(string method, string uri, ref byte[] webdata, ref CookieContainer cookie )
{
//byte[] webdata = null;
bool redir = true;
string vars = "";
string token = bdf.token;
bool json = (token != "");
WebProxy proxy = null;
bool success = MakeByteRequest(method, redir, uri, vars, ref webdata, json, token, ref cookie, proxy);
//string respstr = "";
//if (webdata != null) { respstr = Encoding.ASCII.GetString(webdata); }
return success;
}
*/
// old school object call
public static object[] MakeRequest(string method, bool redir, string uri, string vars, ref CookieContainer cookie, WebProxy proxy)
{
byte[] webdata = null;
string token = bdf.token;
bool json = true;
bool success = MakeByteRequest( method, redir, uri, vars, ref webdata, json, ref token, ref cookie, proxy);
string respstr = "";
if ( webdata != null ) { respstr = Encoding.ASCII.GetString(webdata); }
//Console.WriteLine("{0}",respstr);
return new object[]{ success, respstr };
}
/* public static object[] MakeRequest(string method, bool redir, string uri, string vars, ref CookieContainer cookie, WebProxy proxy)
{
object[] r = MakeByteRequest(method, redir, uri, vars, ref cookie, proxy);
string respstr = "";
if ((byte[])r[1] != null) { respstr = Encoding.ASCII.GetString((byte[])r[1]); }
return new object[] { r[0], respstr };
}
*/
// full feature set call
public static bool MakeByteRequest(string method, bool redir, string uri, string vars, ref byte[] data, bool json, ref string token, ref CookieContainer cookie, WebProxy proxy)
{
bool success = false;
HttpWebRequest webRequest = null;
// Consider setting webRequest.KeepAlive = false; for the logout call to shut down the TCP resources.
// Set the 'Timeout' property in Milliseconds.
//webRequest.Timeout = 1000 * 60 * 3; // 3min
if (method == "GET")
{
webRequest = (HttpWebRequest)WebRequest.Create(string.Format("{0}{1}", uri, vars));
webRequest.Method = "GET";
webRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 OPR/76.0.4017.123";
if (token != "")
{
webRequest.PreAuthenticate = true;
//webRequest.Headers.Add("Authorization", "Bearer " + token);
//webRequest.Headers.Add("Origin", uri); //Feb2023
//webRequest.Headers.Add("Authorization", "Negotiate " + token);
//webRequest.Headers.Add("Authorization", "Negotiate " + token);
//webRequest.Headers.Add("Upgrade-Insecure-Requests", "1");
}
if (json)
{
webRequest.Accept = "application/json";
}
webRequest.AllowAutoRedirect = redir;
webRequest.Method = method;
webRequest.CookieContainer = cookie;
//webRequest.Timeout = 180000; // 3min
webRequest.Timeout = bdf.webMaxWait * 60 * 1000; // convert minutes of wait into milliseconds
if (proxy != null)
{
webRequest.Proxy = proxy;
}
}
else if (method == "POST")
{
byte[] buffer = Encoding.ASCII.GetBytes(vars);
webRequest = (HttpWebRequest)WebRequest.Create(uri);
if (proxy != null)
{
webRequest.Proxy = proxy;
}
webRequest.Method = "POST";
webRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 OPR/76.0.4017.123";
if (token != "") // basically is this a JSON request
{
webRequest.PreAuthenticate = true;
webRequest.Headers.Add("Authorization", "Bearer " + token);
}
if (json)
{
webRequest.Accept = "application/json";
webRequest.ContentType = "application/json";
}
else
{
webRequest.ContentType = "application/x-www-form-urlencoded";
}
webRequest.ContentLength = buffer.Length;
webRequest.AllowAutoRedirect = redir;
webRequest.Method = method;
webRequest.CookieContainer = cookie;
webRequest.Timeout = bdf.webMaxWait * 60 * 1000; // convert minutes of wait into milliseconds
if (proxy != null)
{
webRequest.Proxy = proxy;
}
//We open a stream for writing the postvars
Stream PostData = webRequest.GetRequestStream();
//Now we write, and afterwards, we close. Closing is always important!
PostData.Write(buffer, 0, buffer.Length);
PostData.Close();
}
else
{
Logger.Log("Request not understood");
Logger.Log(3,"FAIL - UNKNOWN METHOD" );
return false;
}
// allows for validation of SSL conversations
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(
ValidateRemoteCertificate
);
HttpWebResponse response = null;
try
{
//ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072 | (SecurityProtocolType)768 | (SecurityProtocolType)192; //3072
//ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls12;
try
{
response = (HttpWebResponse)webRequest.GetResponse();
}
catch (WebException ex)
{
//string authresp = Web_Auth.HttpAuthHandler.ExtractAuthenticateHeader(ex);
//token = authresp.Split(new char[] { ' ' })[1];
Logger.Log(0, "webRequest failed. {0}", ex.Message);
}
//Let's show some information about the response
//Logger.Log(6, "YY {0}", response.StatusCode);
//Logger.Log(6, "ZZ {0}", response.GetResponseHeader("error"));
foreach (Cookie cook in response.Cookies)
{
cookie.Add(cook);
}
//DumpCookies(response.Cookies);
if ((response.StatusCode == HttpStatusCode.Found) ||
(response.StatusCode == HttpStatusCode.OK))
{
success = true;
}
using (Stream s = response.GetResponseStream())
{
//byte[] data = ReadStreamFully(s);
data = ReadStreamFully(s);
s.Close();
//System.IO.StreamWriter file = new System.IO.StreamWriter("webcs.txt"); file.BaseStream.Write(data,0,data.Length); file.Close();
//object[] ret = { success, Encoding.ASCII.GetString(data) , data };
//object[] ret = { success, data };
//return true;
}
return success;
}
catch (Exception ex)
{
Logger.Log(0, "WebRequest error: {0}", ex.Message);
//object[] ret = { false, null };
return false;
}
finally
{
if (response != null)
response.Close();
}
}
/*
public static object[] zMakeByteRequest(string method, bool redir, string uri, string vars, ref CookieContainer cookie, WebProxy proxy)
{
bool success = false;
HttpWebRequest webRequest = null;
// Set the 'Timeout' property in Milliseconds.
//webRequest.Timeout = 1000 * 60 * 3; // 3min
if ( method == "GET" )
{
webRequest = (HttpWebRequest)WebRequest.Create(string.Format("{0}{1}", uri, vars));
webRequest.Method = "GET";
webRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 OPR/76.0.4017.123";
if ( bdf.token != "" )
{
webRequest.PreAuthenticate = true;
webRequest.Headers.Add("Authorization", "Bearer " + bdf.token );
webRequest.Accept = "application/json";
}
webRequest.AllowAutoRedirect = redir;
webRequest.Method = method;
webRequest.CookieContainer = cookie;
//webRequest.Timeout = 180000; // 3min
webRequest.Timeout = bdf.webMaxWait * 60 * 1000; // convert minutes of wait into milliseconds
if (proxy != null)
{
webRequest.Proxy = proxy;
}
}
else if ( method == "POST" )
{
byte[] buffer = Encoding.ASCII.GetBytes(vars);
webRequest = (HttpWebRequest)WebRequest.Create(uri);
if (proxy != null)
{
webRequest.Proxy = proxy;
}
webRequest.Method = "POST";
webRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 OPR/76.0.4017.123";
if ( bdf.token != "" ) // basically is this a JSON request
{
webRequest.PreAuthenticate = true;
webRequest.Headers.Add("Authorization", "Bearer " + bdf.token );
webRequest.Accept = "application/json";
webRequest.ContentType = "application/json";
}
else
{
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.ContentType = "application/json"; // all bdf requests are json
}
webRequest.ContentLength = buffer.Length;
webRequest.AllowAutoRedirect = redir;
webRequest.Method = method;
webRequest.CookieContainer = cookie;
webRequest.Timeout = bdf.webMaxWait * 60 * 1000; // convert minutes of wait into milliseconds
if (proxy != null)
{
webRequest.Proxy = proxy;
}
//We open a stream for writing the postvars
Stream PostData = webRequest.GetRequestStream();
//Now we write, and afterwards, we close. Closing is always important!
PostData.Write(buffer, 0, buffer.Length);
PostData.Close();
}
else
{
Logger.Log("Request not understood");
object[] ret = { false, "FAIL - UNKNOWN METHOD" };
return ret;
}
// allows for validation of SSL conversations
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(
ValidateRemoteCertificate
);
HttpWebResponse response = null;
try
{
//ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072 | (SecurityProtocolType)768 | (SecurityProtocolType)192; //3072
//ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls12;
response = (HttpWebResponse)webRequest.GetResponse();
//Let's show some information about the response
Logger.Log(6,"{0}",response.StatusCode);
foreach (Cookie cook in response.Cookies)
{
cookie.Add(cook);
}
//DumpCookies(response.Cookies);
if ( ( response.StatusCode == HttpStatusCode.Found ) ||
( response.StatusCode == HttpStatusCode.OK ) )
{
success = true;
}
using (Stream s = response.GetResponseStream() )
{
byte[] data = ReadStreamFully(s);
s.Close();
//System.IO.StreamWriter file = new System.IO.StreamWriter("webcs.txt"); file.BaseStream.Write(data,0,data.Length); file.Close();
//object[] ret = { success, Encoding.ASCII.GetString(data) , data };
object[] ret = { success, data };
return ret;
}
}
catch (Exception ex)
{
Logger.Log(0,"WebRequest error: {0}",ex.Message);
object[] ret = { false, null };
return ret;
}
finally
{
if (response != null)
response.Close();
}
}
*/
public static byte[] ReadStreamFully (Stream stream)
{
byte[] buffer = new byte[32768];
using (MemoryStream ms = new MemoryStream())
{
while (true)
{
int read = stream.Read (buffer, 0, buffer.Length);
if (read <= 0)
//return ms;
return ms.ToArray();
ms.Write (buffer, 0, read);
}
}
}
// callback used to validate the certificate in an SSL conversation
private static bool ValidateRemoteCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors policyErrors
)
{
/*if (Convert.ToBoolean(ConfigurationManager.AppSettings["IgnoreSslErrors"]))
{
// allow any old dodgy certificate...
return true;
}
else
{
return policyErrors == SslPolicyErrors.None;
}
*/
return true; //policyErrors == SslPolicyErrors.None;
}
/*
private static void DumpCookies ( System.Net.CookieCollection ckjar )
{
foreach (Cookie cook in ckjar)
//foreach (Cookie cook in cookie)
{
Logger.Log("Cookie:");
Logger.Log(0, "{0} = {1}", cook.Name, cook.Value);
Logger.Log(0, "Domain: {0}", cook.Domain);
Logger.Log(0, "Path: {0}", cook.Path);
Logger.Log(0, "Port: {0}", cook.Port);
Logger.Log(0, "Secure: {0}", cook.Secure);
Logger.Log(0, "When issued: {0}", cook.TimeStamp);
Logger.Log(0, "Expires: {0} (expired? {1})",
cook.Expires, cook.Expired);
Logger.Log(0, "Don't save: {0}", cook.Discard);
Logger.Log(0, "Comment: {0}", cook.Comment);
Logger.Log(0, "Uri for comments: {0}", cook.CommentUri);
Logger.Log(0, "Version: RFC {0}" , cook.Version == 1 ? "2109" : "2965");
// Show the string representation of the cookie.
Logger.Log (0, "String: {0}", cook.ToString());
}
}
*/
}
}

380
XLimport.cs Normal file
View File

@@ -0,0 +1,380 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
namespace bdf
{
class CXLFile
{
//public static List<XLWorkbook> ServiceOrders = new List<XLWorkbook> { };
public static List<Spire.Xls.Workbook> S_ServiceOrders = new List<Spire.Xls.Workbook> { };
public static void S_getXLS(string task, string dir)
{
//string folderPath = dir;
string filePrefix1 = "ROGERS_";
string filePrefix2 = task + "_SO";
var excelFiles = getLatestVersionFiles(dir, filePrefix1, filePrefix2);
if ( (excelFiles.Length == 0) || (excelFiles == null) )
{
Console.WriteLine("No Excel files found with prefix: " + filePrefix1 + "*" + filePrefix2);
//throw new System.ArgumentNullException("filePaths");
return;
}
foreach (string path in excelFiles)
{
if (string.IsNullOrWhiteSpace(path))
continue;
if (!System.IO.File.Exists(path))
throw new System.IO.FileNotFoundException(
"Excel file not found.", path);
Logger.Log(1, "Scanning: {0}", Path.GetFileName(path));
// Create a new workbook and load the file
Spire.Xls.Workbook wb = new Spire.Xls.Workbook();
//straight up load from file
//wb.LoadFromFile(path); // FreeSpire autodetects .xls vs .xlsx
//more network savvy way that handles sharepoint's idiosyncrasies
FileStream stream = null;
// OneDrive sync engine frequently locks files briefly:
const int maxRetries = 12;
const int retryDelayMs = 150;
for (int i = 0; i < maxRetries; i++)
{
try
{
stream = new FileStream(
path,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite | FileShare.Delete
);
break; // opened successfully
}
catch (IOException)
{
if (i == maxRetries - 1)
throw;
System.Threading.Thread.Sleep(retryDelayMs);
}
}
wb.LoadFromStream(stream);
Logger.Log(5, " -loaded SO={0}", wb.Worksheets[1][2, 1].Value.ToString() );
S_ServiceOrders.Add(wb);
}
Logger.Log("All SO Excel files processed successfully.");
return; // S_ServiceOrders;
}
// This routine is wholly dependent on the filename structure being ROGERS*LDF*_SO*VER*number
// in future should just open each workbook and read exact version from the first worksheet.
public static string[] getLatestVersionFiles(string folder, string prefixA, string prefixB)
{
var files = Directory.GetFiles(folder);
// Build wildcard pattern:
// file must contain prefixA ... anything ... prefixB
Func<string, bool> matchesPrefix = name =>
name.IndexOf(prefixA, StringComparison.OrdinalIgnoreCase) >= 0 &&
name.IndexOf(prefixB, StringComparison.OrdinalIgnoreCase) >
name.IndexOf(prefixA, StringComparison.OrdinalIgnoreCase);
var filtered = files
.Where(f => matchesPrefix(Path.GetFileName(f)))
.ToList();
// Serial = 6 digits
// After "VER" allow ANY non-digit characters, then the version number
var regex = new Regex(
@"(?<serial>\d{6}).*?VER\D*(?<ver>\d+)",
RegexOptions.IgnoreCase
);
Dictionary<string, (int version, string file)> best =
new Dictionary<string, (int, string)>();
foreach (var file in files)
{
string name = Path.GetFileName(file);
var match = regex.Match(name);
if (!match.Success)
{
Logger.Log(1, " Did not find SO and Version for file {0}", name);
continue;
}
string serial = match.Groups["serial"].Value;
if (!int.TryParse(match.Groups["ver"].Value, out int ver))
{
Logger.Log(1, " Did not extract Version for file {0}", name);
continue;
}
// Keep highest version per serial
if (!best.ContainsKey(serial)) // || ver > best[serial].version)
{
best[serial] = (ver, file);
Logger.Log(5, " Adding: {0} ver {1}", serial, ver);
}
else if (ver > best[serial].version)
{
Logger.Log(2, " Replacing: {0} ver {1} with ver {2}", serial, best[serial].version, ver);
best[serial] = (ver, file);
}
else
{
Logger.Log(4, " Ignoring: {0} v.{1}", serial, ver);
}
}
return best.Values.Select(v => v.file).ToArray();
}
/*
public static void getXLS(string task, string dir)
{
//string folderPath = @"C:\Data\ExcelFiles"; // Folder to scan
string folderPath = dir;
string filePrefix1 = "ROGERS_";
string filePrefix2 = task + "_SO";
//List<XLWorkbook> ServiceOrders = new List<XLWorkbook> { };
try
{
// Required for ExcelDataReader in .NET 4
System.Text.Encoding.RegisterProvider(
System.Text.CodePagesEncodingProvider.Instance);
// Get all Excel files that match the prefix
//var excelFiles = Directory.GetFiles(folderPath, filePrefix1 + "*" + filePrefix2 + "*.xls*", SearchOption.TopDirectoryOnly);
var excelFiles = getLatestVersionFiles(dir, filePrefix1, filePrefix2);
if (excelFiles.Length == 0)
{
Console.WriteLine("No Excel files found with prefix: " + filePrefix1 + "*" + filePrefix2);
return;
}
DataSet _dataSet = null;
foreach (var filePath in excelFiles)
{
Logger.Log(1, "Scanning: {0}", Path.GetFileName(filePath));
// DataSet dataSet = ReadExcelFile(filePath);
// STEP 1: Read file into DataSet using ExcelDataReader
try
{
_dataSet = ReadExcelFile(filePath);
//_dataSet = LoadOneDriveDataSet(filePath);
}
catch
{
try
{
_dataSet = LoadOneDriveDataSet(filePath);
}
catch (Exception e)
{
Logger.Log(0, "Error trying to access file {0}. ({1})", filePath, e.Message);
}
}
// STEP 2: Convert DataSet into a ClosedXML workbook for manipulation
var workbook = new XLWorkbook();
//using (var workbook = new XLWorkbook())
{
foreach (DataTable table in _dataSet.Tables)
{
var worksheet = workbook.Worksheets.Add(table.TableName);
// Insert headers
for (int col = 0; col < table.Columns.Count; col++)
{
worksheet.Cell(1, col + 1).Value = table.Columns[col].ColumnName;
worksheet.Cell(1, col + 1).Style.Font.Bold = true;
}
// Insert rows
for (int row = 0; row < table.Rows.Count; row++)
{
for (int col = 0; col < table.Columns.Count; col++)
{
//Logger.Log(5, "type is {0}", table.Rows[row][col].GetType().Name);
string valuetype = table.Rows[row][col].GetType().Name;
if (valuetype == "Int32")
{
worksheet.Cell(row + 2, col + 1).Value = (Int32)table.Rows[row][col];
}
else if (valuetype == "String")
{
worksheet.Cell(row + 2, col + 1).Value = (String)table.Rows[row][col];
}
else if (valuetype == "Decimal")
{
worksheet.Cell(row + 2, col + 1).Value = (Decimal)table.Rows[row][col];
}
else if (valuetype == "Double")
{
worksheet.Cell(row + 2, col + 1).Value = (Double)table.Rows[row][col];
}
else if (valuetype == "DBNull")
{
worksheet.Cell(row + 2, col + 1).Value = "";
}
else
{
worksheet.Cell(row + 2, col + 1).Value = "fix me";
}
//worksheet.Cell(row + 2, col + 1).Value = table.Rows[row][col];
}
}
worksheet.Columns().AdjustToContents();
//Logger.Log(0, "Sheet{0} Value={1}", workbook.Worksheets.Count, workbook.Worksheet(workbook.Worksheets.Count).Cell("C2").Value);
}
// Example: Save modified workbook (optional)
string outputFile = Path.Combine(folderPath, "" + Path.GetFileName(filePath) + "x");
//workbook.SaveAs(outputFile);
Logger.Log(7, "Processed file: {0}", outputFile);
//Logger.Log(0, "Book has {0} sheets", workbook.Worksheets.Count );
CXLFile.ServiceOrders.Add(workbook);
//Logger.Log("test: " + workbook.Worksheet(1).Cell("C2").Value);
}
//Logger.Log("Finished: " + Path.GetFileName(filePath));
//Logger.Log(new string('-', 50));
}
Logger.Log("All SO Excel files processed successfully.");
}
catch (Exception ex)
{
Logger.Log(0, "SO processing error: {0}" + ex.Message);
//Logger.Log("Press any key to exit...");
//Console.ReadKey();
}
//
//return ServiceOrders;
}
/// <summary>
/// Reads an Excel file into a DataSet using ExcelDataReader.
/// Each worksheet becomes a DataTable.
/// </summary>
static DataSet ReadExcelFile(string filePath)
{
// Required for ExcelDataReader to process XLS files
System.Text.Encoding.RegisterProvider(
System.Text.CodePagesEncodingProvider.Instance);
using (var stream = System.IO.File.Open(filePath, FileMode.Open, FileAccess.Read))
{
IExcelDataReader reader;
// Auto-detect format (XLS or XLSX)
if (Path.GetExtension(filePath).Equals(".xls", StringComparison.OrdinalIgnoreCase))
reader = ExcelReaderFactory.CreateBinaryReader(stream);
else
reader = ExcelReaderFactory.CreateOpenXmlReader(stream);
// Convert to DataSet (with first row as header)
var result = reader.AsDataSet(new ExcelDataSetConfiguration()
{
ConfigureDataTable = _ => new ExcelDataTableConfiguration()
{
UseHeaderRow = true
}
});
reader.Close();
return result;
}
}
public static DataSet LoadOneDriveDataSet(string path)
{
if (!System.IO.File.Exists(path))
throw new FileNotFoundException("OneDrive file not found.", path);
// Required for ExcelDataReader to process XLS files
System.Text.Encoding.RegisterProvider(
System.Text.CodePagesEncodingProvider.Instance);
FileStream stream = null;
// OneDrive sync engine frequently locks files briefly:
const int maxRetries = 12;
const int retryDelayMs = 150;
for (int i = 0; i < maxRetries; i++)
{
try
{
stream = new FileStream(
path,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite | FileShare.Delete
);
break; // opened successfully
}
catch (IOException)
{
if (i == maxRetries - 1)
throw;
System.Threading.Thread.Sleep(retryDelayMs);
}
}
// STEP 1: Read the workbook into a DataSet (ExcelDataReader)
DataSet dataSet;
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
dataSet = reader.AsDataSet(new ExcelDataSetConfiguration
{
ConfigureDataTable = _ => new ExcelDataTableConfiguration
{
UseHeaderRow = true
}
});
}
return dataSet;
}
*/
}
}

1581
_Main - Copy.cs Executable file

File diff suppressed because it is too large Load Diff

2082
_Main.cs Normal file

File diff suppressed because it is too large Load Diff

6
app.config Executable file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
</startup>
</configuration>

BIN
arial.ttf Executable file

Binary file not shown.

136
bdf.csproj Normal file
View File

@@ -0,0 +1,136 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<PropertyGroup>
<ProjectGuid>{6166EEDD-31E3-44EB-978A-5EAF9C2992FF}</ProjectGuid>
<ProjectTypeGuids>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<OutputType>Exe</OutputType>
<RootNamespace>BDF</RootNamespace>
<AssemblyName>bdf</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<AppDesignerFolder>Properties</AppDesignerFolder>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ReleaseVersion>1.0</ReleaseVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<OutputPath>bin\Debug\</OutputPath>
<DebugSymbols>True</DebugSymbols>
<DebugType>Full</DebugType>
<Optimize>False</Optimize>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<DefineConstants>DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>bin\Release\</OutputPath>
<DebugSymbols>False</DebugSymbols>
<DebugType>None</DebugType>
<Optimize>True</Optimize>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DefineConstants>DEBUG</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="Arguments.cs" />
<Compile Include="Logger.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="_Main.cs" />
<Compile Include="BDF.cs" />
<Compile Include="XLimport.cs" />
<Compile Include="Web.cs" />
<Compile Include="MegaT.cs" />
<Compile Include="PDF.cs" />
<Compile Include="SFTP.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Reference Include="Spire.XLS">
<HintPath>packages\FreeSpire.XLS.14.2.0\lib\net48\Spire.XLS.dll</HintPath>
</Reference>
<Reference Include="BouncyCastle.Cryptography">
<HintPath>packages\BouncyCastle.Cryptography.2.6.2\lib\net461\BouncyCastle.Cryptography.dll</HintPath>
</Reference>
<Reference Include="System.Buffers">
<HintPath>packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Numerics.Vectors">
<HintPath>packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe">
<HintPath>packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Memory">
<HintPath>packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions">
<HintPath>packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bcl.AsyncInterfaces">
<HintPath>packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions">
<HintPath>packages\Microsoft.Extensions.DependencyInjection.Abstractions.8.0.2\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Logging.Abstractions">
<HintPath>packages\Microsoft.Extensions.Logging.Abstractions.8.0.3\lib\net462\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple">
<HintPath>packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Formats.Asn1">
<HintPath>packages\System.Formats.Asn1.8.0.2\lib\net462\System.Formats.Asn1.dll</HintPath>
</Reference>
<Reference Include="Renci.SshNet">
<HintPath>packages\SSH.NET.2025.1.0\lib\net462\Renci.SshNet.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Folder Include="Embedded\" />
</ItemGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="WindowsBase" />
<Reference Include="System.Numerics" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Security" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Drawing" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Embedded\Spire.XLS.dll" />
<EmbeddedResource Include="Embedded\template.xlsx" />
<EmbeddedResource Include="Embedded\arial.ttf" />
<EmbeddedResource Include="Embedded\Renci.SshNet.dll" />
<EmbeddedResource Include="Embedded\BouncyCastle.Cryptography.dll" />
<EmbeddedResource Include="Embedded\System.Formats.Asn1.dll" />
<EmbeddedResource Include="Embedded\Microsoft.Extensions.Logging.Abstractions.dll" />
<EmbeddedResource Include="Embedded\Microsoft.Extensions.DependencyInjection.Abstractions.dll" />
<EmbeddedResource Include="Embedded\Microsoft.Bcl.AsyncInterfaces.dll" />
<EmbeddedResource Include="Embedded\System.Memory.dll" />
<EmbeddedResource Include="Embedded\System.Buffers.dll" />
<EmbeddedResource Include="Embedded\System.Threading.Tasks.Extensions.dll" />
<EmbeddedResource Include="Embedded\System.Runtime.CompilerServices.Unsafe.dll" />
<EmbeddedResource Include="Embedded\System.ValueTuple.dll" />
<EmbeddedResource Include="Embedded\System.Numerics.Vectors.dll" />
<EmbeddedResource Include="Embedded\private_passphr.ppk" />
<EmbeddedResource Include="Embedded\private_nopassphr.ppk" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

20
bdf.sln Executable file
View File

@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBF}") = "bdf", "bdf.csproj", "{6166EEDD-31E3-44EB-978A-5EAF9C2992FF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6166EEDD-31E3-44EB-978A-5EAF9C2992FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6166EEDD-31E3-44EB-978A-5EAF9C2992FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6166EEDD-31E3-44EB-978A-5EAF9C2992FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6166EEDD-31E3-44EB-978A-5EAF9C2992FF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
description = Automation of Detailed Billing Files.
version = 1.0
EndGlobalSection
EndGlobal

337
conv.cs Executable file
View File

@@ -0,0 +1,337 @@
using System;
using Spire.Xls;
//using Spire.Xls;
using System.IO;
using System.Diagnostics;
using Excel2PDF;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices;
namespace Excel2PDF
{
public class InvoiceCell // Invoice Cells from Invoice Template
{
public String Account { get; set; } = "I2"; // "Account"+ (also I32)
public String Date { get; set; } = "I3"; // I3 (also I33)
public String Invoice { get; set; } = "I4"; //I4 "Invoice" (also I34)
public String Total_Charges { get; set; } = "I14"; //I14 (also I36)
public String Account2 { get; set; } = "I32"; // "Account"+ (also I32)
public String Date2 { get; set; } = "I33"; // I3 (also I33)
public String Invoice2 { get; set; } = "I34"; //I4 "Invoice" (also I34)
public String Total_Charges2 { get; set; } = "I36"; //I14 (also I36)
public String CCI { get; set; } = "C12"; // C12 "Canada Contract Identifier"
public String PaperFee { get; set; } = "H17";
public String LateCharge { get; set; } = "H18";
public String Service_Charges { get; set; } = "I19";
public String UsageCharges { get; set; } = "H20";
public String TotalUsageCharges { get; set; } = "I21";
public String DataMonthlyCharges { get; set; } = "H23";
public String DataNon_RecurringCharges { get; set; } = "H24";
public String DataTotalOtherCharges { get; set; } = "H25";
public String Data_Services { get; set; } = "I27";
public String TaxON_PST { get; set; } = "F29";
public String TaxON_GST { get; set; } = "G29";
public String TaxON_HST { get; set; } = "H29";
public String TaxPQ_PST { get; set; } = "F30";
public String TaxPQ_GST { get; set; } = "G30";
public String TaxPQ_HST { get; set; } = "H30";
public String Taxes { get; set; } = "I31";
}
// Source - https://stackoverflow.com/a
// Posted by Alexandru
// Retrieved 2025-12-03, License - CC BY-SA 3.0
internal class OutputSink : IDisposable
{
[DllImport("kernel32.dll")]
public static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll")]
public static extern int SetStdHandle(int nStdHandle, IntPtr hHandle);
private readonly TextWriter _oldOut;
private readonly TextWriter _oldError;
private readonly IntPtr _oldOutHandle;
private readonly IntPtr _oldErrorHandle;
public OutputSink()
{
_oldOutHandle = GetStdHandle(-11);
_oldErrorHandle = GetStdHandle(-12);
_oldOut = Console.Out;
_oldError = Console.Error;
Console.SetOut(TextWriter.Null);
Console.SetError(TextWriter.Null);
SetStdHandle(-11, IntPtr.Zero);
SetStdHandle(-12, IntPtr.Zero);
}
public void Dispose()
{
SetStdHandle(-11, _oldOutHandle);
SetStdHandle(-12, _oldErrorHandle);
Console.SetOut(_oldOut);
Console.SetError(_oldError);
}
}
internal class Program
{
static void Main(string[] args)
{
//MakePDF();
Dictionary<string,string> Invoice = new Dictionary<string,string> { };
InvoiceCell ic = new InvoiceCell { };
Invoice.Add( ic.Account , "Account P02-" + "123456"); //bdf2 C2
int d = 20250731;
Invoice.Add( ic.Date , dateFormal(d));
//string dt = "20250930";
Invoice.Add( ic.Invoice , ( "Invoice " + d.ToString().Substring(4) + d.ToString().Substring(0, 4) + " - NU" ) ); //mmddyyyy
Invoice.Add( ic.Total_Charges , String.Format("${0:n}",10000) );
Invoice.Add( ic.Account2 , Invoice[ic.Account]);
Invoice.Add( ic.Date2 , Invoice[ic.Date]);
Invoice.Add( ic.Invoice2 , Invoice[ic.Invoice]);
Invoice.Add( ic.Total_Charges2 , Invoice[ic.Total_Charges]);
customInvoice("doug", ref Invoice);
}
static void MakePDF()
{
// Create a Workbook object
Spire.Xls.Workbook workbook = new Spire.Xls.Workbook();
// Load an Excel file (replace with your file path)
workbook.LoadFromFile("test.xlsx");
//PdfFont fieldFont = new PdfFont(PdfFontFamily.Helvetica, 10f);
// Get the first worksheet
Spire.Xls.Worksheet sheet = workbook.Worksheets[0];
// Set the print area to a specific cell range
// Comment this line out if you need to export the entire worksheet as a PDF
//sheet.PageSetup.PrintArea = "B1:E6";
// Optional: Set worksheets to fit to page when converting
workbook.ConverterSetting.SheetFitToPage = true;
// Save the Excel file to PDF
workbook.SaveToFile("Output.pdf", FileFormat.PDF);
// Dispose resources
workbook.Dispose();
}
static void LoadStream()
{
// 1. Create a Workbook instance
Workbook workbook = new Workbook();
// 2. Create a Stream object (example using FileStream)
// Replace "sample.xls" with your actual file path or retrieve the stream from your source
FileStream fileStream = File.OpenRead("sample.xls");
// Ensure the stream position is at the beginning (if necessary)
fileStream.Seek(0, SeekOrigin.Begin);
// 3. Use the Workbook.LoadFromStream() method to load the file
try
{
workbook.LoadFromStream(fileStream);
}
catch (Exception ex)
{
// Handle exceptions, e.g., file format not supported (Excel 95 or earlier not supported)
Console.WriteLine($"Error loading stream: {ex.Message}");
}
finally
{
// 4. Close the stream after loading
fileStream.Dispose();
}
// Now you can work with the workbook data
Worksheet sheet = workbook.Worksheets[0];
// ... do operations like reading cells, etc. ...
// Example of saving the processed file to a new file
workbook.SaveToFile("From_stream_processed.xls", ExcelVersion.Version97to2003);
Process.Start("From_stream_processed.xls");
}
static void LoadStreamXLSX()
{
// 1. Create a Workbook instance
Workbook workbook = new Workbook();
// 2. Open a FileStream from your source file
using (FileStream fileStream = File.OpenRead("Sample.xlsx"))
{
// Ensure the stream position is at the beginning
fileStream.Seek(0, SeekOrigin.Begin);
// 3. Load the workbook from the stream
workbook.LoadFromStream(fileStream);
// 4. (Optional) Work with the workbook, e.g., modify a cell
workbook.Worksheets[0].Range["A1"].Text = "Data loaded from stream!";
// (Optional) Save the result to a new stream or file
// workbook.SaveToStream(outputStream);
// workbook.SaveToFile("Output.xlsx", ExcelVersion.Version2016);
}
}
static void customInvoice(string type, ref Dictionary<string,string> CellData)
{
//string fontDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "");
string fontDirectory = AppDomain.CurrentDomain.BaseDirectory;
string[] fontDirectories = { fontDirectory };
/* Set the custom font file directory for the workbook instance
TextWriter originalOutput = Console.Out;
// Temporarily suppress console output
Console.SetOut(TextWriter.Null);
Workbook workbook = new Workbook(); // spews Not Implemented error
// Restore the original standard output writer
//Console.SetError(originalOutput);
//Console.SetOut(originalOutput);
/*
// Store the original listeners
var originalListeners = Debug.Listeners;
// Temporarily clear the listeners to suppress all Debug output
Debug.Listeners.Clear();
// Code here that generates unwanted debug output (e.g., a noisy library call)
Workbook workbook = new Workbook(); // spews Not Implemented error
// Re-add the original listeners (or just the DefaultTraceListener)
Debug.Listeners.Add(new DefaultTraceListener());
*/
Workbook workbook = new Workbook();
/*
using (new OutputSink())
{
Console.WriteLine("a");
workbook = new Workbook(); // spews Not Implemented error
Console.WriteLine("b");
}
*/
workbook.CustomFontFileDirectory = fontDirectories;
//Console.WriteLine("c");
// 1. Create a Workbook instance
//Workbook workbook = new Workbook();
// 2. Open a FileStream from your source file
using (FileStream fileStream = File.OpenRead("test.xlsx"))
{
// Ensure the stream position is at the beginning
fileStream.Seek(0, SeekOrigin.Begin);
// 3. Load the workbook from the stream
workbook.LoadFromStream(fileStream);
// 4. (Optional) Work with the workbook, e.g., modify a cell
foreach( var cell in CellData)
{
// workbook.Worksheets[0].Range["A1"].Text = "Data loaded from stream!";
workbook.Worksheets[0].Range[cell.Key].Text = cell.Value;
} // end foreach
//Spire.Xls.Worksheet sheet = workbook.Worksheets[0];
// Set the print area to a specific cell range
// Comment this line out if you need to export the entire worksheet as a PDF
//sheet.PageSetup.PrintArea = "B1:E6";
// Optional: Set worksheets to fit to page when converting
workbook.ConverterSetting.SheetFitToPage = true;
// (Optional) Save the result to a new stream or file
// workbook.SaveToStream(outputStream);
// workbook.SaveToFile("Output.xlsx", ExcelVersion.Version2016);
// Save the Excel file to PDF
string pdf_name = "Output_" + type + ".pdf";
workbook.SaveToFile("Output.pdf", FileFormat.PDF);
} //end using
}
public static string dateFormal(int dateInt)
{
//int dateInt = 20251130;
string dateString = dateInt.ToString();
// 1. Define the input format ("yyyyMMdd")
string inputFormat = "yyyyMMdd";
// 2. Parse the string into a DateTime object
DateTime dateTimeObject = DateTime.ParseExact(
dateString,
inputFormat,
CultureInfo.InvariantCulture
);
// 3. Define the desired output format ("MMMM dd, yyyy")
// MMMM = Full month name
// dd = Day of the month
// yyyy = Year
string outputFormat = "MMMM d, yyyy";
string result = dateTimeObject.ToString(outputFormat);
//Console.WriteLine(result);
// Output: November 30, 2025
return result;
}
}
}
/*
// Ensure these files are present in this directory in your application's deployment environment.
string fontDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Fonts");
string[] fontDirectories = { fontDirectory };
// Set the custom font file directory for the workbook instance
Workbook workbook = new Workbook();
workbook.CustomFontFileDirectory = fontDirectories; //
// Load your Excel file
workbook.LoadFromFile("InputFile.xls");
// ... perform other operations ...
// When saving or converting (e.g., to PDF), the library will check the specified path for fonts
workbook.SaveToFile("OutputFile.xlsx", ExcelVersion.Version2013);
*/

BIN
conv.exe Executable file

Binary file not shown.

86
logfile.txt Executable file
View File

@@ -0,0 +1,86 @@
[11/30/2025 14:21:58] ╔════════════════════════════════════╗
[11/30/2025 14:21:58] ║ BDF v2.0.1 (c) 2025 Doug Macintosh ║
[11/30/2025 14:21:58] ╚════════════════════════════════════╝
[11/30/2025 14:21:58] --- call (613)697-9178 for support ---
[11/30/2025 14:21:58] usage: bdf.exe [-options]
[11/30/2025 14:21:58] login: -u user -p passwd
[11/30/2025 14:21:58] detail files: -all OR any combo of -ldf -wav -sip
[11/30/2025 14:21:58] output path: -path /directory/subdir
[11/30/2025 14:21:58] SO basepath: -so C:\Users\us.er\OneDrive\path\
[11/30/2025 14:21:58] subdirs: -ldfdir .\LDF\ | -wavdir .\WAV\ | -sipdir .\SIP\
[11/30/2025 14:21:58] inv offset: -month=x [x = +/- 6, default is coming bill cycle, ie '1']
[11/30/2025 14:21:58] reuse: -reuse
[11/30/2025 14:21:58] redo: -redo
[11/30/2025 14:21:58] verbose: -v
[2025-12-05 2:56:09 PM] ╔════════════════════════════════════╗
[2025-12-05 2:56:09 PM] ║ BDF v2.0.1 (c) 2025 Doug Macintosh ║
[2025-12-05 2:56:09 PM] ╚════════════════════════════════════╝
[2025-12-05 2:56:09 PM] --- call (613)697-9178 for support ---
[2025-12-05 2:56:09 PM] Generating Bill Detail files for: SIP
[2025-12-05 2:56:09 PM] SO Base Path: C:\Users\Doug.Macintosh\OneDrive - Rogers Communications Inc\Jeff Hawthorne's files - GCNS Stream 5 - Dark Fibre - Billing BDF Files\
[2025-12-05 2:56:09 PM] SIP SO files expected in sub-directory: .\SIP Service Orders\
[2025-12-05 2:56:09 PM] Starting to process the SIP BDF...
[2025-12-05 2:56:09 PM] Initiating connection...
[2025-12-05 2:56:09 PM] ** Password is required to access Megatool. You must be on the Corporate Lan/VPN.**
[2025-12-05 2:56:09 PM] Please enter the password for (RCI\Doug.Macintosh) and hit Return.
[2025-12-05 2:56:18 PM] Found 6 active SSCGPASxxx SCHEDAs
[2025-12-05 2:58:41 PM] ╔════════════════════════════════════╗
[2025-12-05 2:58:41 PM] ║ BDF v2.0.1 (c) 2025 Doug Macintosh ║
[2025-12-05 2:58:41 PM] ╚════════════════════════════════════╝
[2025-12-05 2:58:41 PM] --- call (613)697-9178 for support ---
[2025-12-05 2:58:41 PM] Generating Bill Detail files for: SIP
[2025-12-05 2:58:41 PM] SO Base Path: C:\Users\Doug.Macintosh\OneDrive - Rogers Communications Inc\Jeff Hawthorne's files - GCNS Stream 5 - Dark Fibre - Billing BDF Files\
[2025-12-05 2:58:41 PM] SIP SO files expected in sub-directory: .\SIP Service Orders\
[2025-12-05 2:58:41 PM] Starting to process the SIP BDF...
[2025-12-05 2:58:41 PM] Initiating connection...
[2025-12-05 2:58:41 PM] ** Password is required to access Megatool. You must be on the Corporate Lan/VPN.**
[2025-12-05 2:58:41 PM] Please enter the password for (RCI\Doug.Macintosh) and hit Return.
[2025-12-05 2:58:48 PM] Found 6 active SSCGPASxxx SCHEDAs
[2025-12-05 3:04:24 PM] ╔════════════════════════════════════╗
[2025-12-05 3:04:25 PM] ║ BDF v2.0.1 (c) 2025 Doug Macintosh ║
[2025-12-05 3:04:25 PM] ╚════════════════════════════════════╝
[2025-12-05 3:04:25 PM] --- call (613)697-9178 for support ---
[2025-12-05 3:04:25 PM] Generating Bill Detail files for: SIP
[2025-12-05 3:04:25 PM] SO Base Path: C:\Users\Doug.Macintosh\OneDrive - Rogers Communications Inc\Jeff Hawthorne's files - GCNS Stream 5 - Dark Fibre - Billing BDF Files\
[2025-12-05 3:04:25 PM] SIP SO files expected in sub-directory: .\SIP Service Orders\
[2025-12-05 3:04:25 PM] Starting to process the SIP BDF...
[2025-12-05 3:04:27 PM] Initiating connection...
[2025-12-05 3:04:27 PM] ** Password is required to access Megatool. You must be on the Corporate Lan/VPN.**
[2025-12-05 3:04:27 PM] Please enter the password for (RCI\Doug.Macintosh) and hit Return.
[2025-12-05 3:04:36 PM] Found 6 active SSCGPASxxx SCHEDAs
[2025-12-05 3:05:16 PM] ╔════════════════════════════════════╗
[2025-12-05 3:05:16 PM] ║ BDF v2.0.1 (c) 2025 Doug Macintosh ║
[2025-12-05 3:05:16 PM] ╚════════════════════════════════════╝
[2025-12-05 3:05:16 PM] --- call (613)697-9178 for support ---
[2025-12-05 3:05:16 PM] Generating Bill Detail files for: SIP
[2025-12-05 3:05:16 PM] SO Base Path: C:\Users\Doug.Macintosh\OneDrive - Rogers Communications Inc\Jeff Hawthorne's files - GCNS Stream 5 - Dark Fibre - Billing BDF Files\
[2025-12-05 3:05:16 PM] SIP SO files expected in sub-directory: .\SIP Service Orders\
[2025-12-05 3:05:16 PM] Starting to process the SIP BDF...
[2025-12-05 3:05:16 PM] Initiating connection...
[2025-12-05 3:05:16 PM] ** Password is required to access Megatool. You must be on the Corporate Lan/VPN.**
[2025-12-05 3:05:16 PM] Please enter the password for (RCI\Doug.Macintosh) and hit Return.
[2025-12-05 3:05:23 PM] Found 6 active SSCGPASxxx SCHEDAs
[2025-12-05 3:07:40 PM] ╔════════════════════════════════════╗
[2025-12-05 3:07:40 PM] ║ BDF v2.0.1 (c) 2025 Doug Macintosh ║
[2025-12-05 3:07:40 PM] ╚════════════════════════════════════╝
[2025-12-05 3:07:40 PM] --- call (613)697-9178 for support ---
[2025-12-05 3:07:40 PM] Generating Bill Detail files for: SIP
[2025-12-05 3:07:40 PM] SO Base Path: C:\Users\Doug.Macintosh\OneDrive - Rogers Communications Inc\Jeff Hawthorne's files - GCNS Stream 5 - Dark Fibre - Billing BDF Files\
[2025-12-05 3:07:40 PM] SIP SO files expected in sub-directory: .\SIP Service Orders\
[2025-12-05 3:07:40 PM] Starting to process the SIP BDF...
[2025-12-05 3:07:40 PM] Initiating connection...
[2025-12-05 3:07:40 PM] ** Password is required to access Megatool. You must be on the Corporate Lan/VPN.**
[2025-12-05 3:07:40 PM] Please enter the password for (RCI\Doug.Macintosh) and hit Return.
[2025-12-05 3:07:51 PM] Found 6 active SSCGPASxxx SCHEDAs
[2025-12-05 3:09:12 PM] ╔════════════════════════════════════╗
[2025-12-05 3:09:12 PM] ║ BDF v2.0.1 (c) 2025 Doug Macintosh ║
[2025-12-05 3:09:12 PM] ╚════════════════════════════════════╝
[2025-12-05 3:09:12 PM] --- call (613)697-9178 for support ---
[2025-12-05 3:09:12 PM] Generating Bill Detail files for: SIP
[2025-12-05 3:09:12 PM] SO Base Path: C:\Users\Doug.Macintosh\OneDrive - Rogers Communications Inc\Jeff Hawthorne's files - GCNS Stream 5 - Dark Fibre - Billing BDF Files\
[2025-12-05 3:09:12 PM] SIP SO files expected in sub-directory: .\SIP Service Orders\
[2025-12-05 3:09:12 PM] Starting to process the SIP BDF...
[2025-12-05 3:09:12 PM] Initiating connection...
[2025-12-05 3:09:12 PM] ** Password is required to access Megatool. You must be on the Corporate Lan/VPN.**
[2025-12-05 3:09:12 PM] Please enter the password for (RCI\Doug.Macintosh) and hit Return.
[2025-12-05 3:09:24 PM] Found 6 active SSCGPASxxx SCHEDAs

16
packages.config Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BouncyCastle.Cryptography" version="2.6.2" targetFramework="net48" />
<package id="FreeSpire.XLS" version="14.2.0" targetFramework="net48" />
<package id="Microsoft.Bcl.AsyncInterfaces" version="8.0.0" targetFramework="net48" />
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="8.0.2" targetFramework="net48" />
<package id="Microsoft.Extensions.Logging.Abstractions" version="8.0.3" targetFramework="net48" />
<package id="SSH.NET" version="2025.1.0" targetFramework="net48" />
<package id="System.Buffers" version="4.5.1" targetFramework="net48" />
<package id="System.Formats.Asn1" version="8.0.2" targetFramework="net48" />
<package id="System.Memory" version="4.5.5" targetFramework="net48" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net48" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.3" targetFramework="net48" />
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net48" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net48" />
</packages>

31
private_Rogers1!.ppk Normal file
View File

@@ -0,0 +1,31 @@
PuTTY-User-Key-File-3: ssh-rsa
Encryption: aes256-cbc
Comment: rsa-key-20251222
Public-Lines: 6
AAAAB3NzaC1yc2EAAAADAQABAAABAQCkhl4EpiCvmTBENERzih8VHL4AzDJfm08e
mA+PYg+mWhrM8eZ79zuAdy6NJHlyP0ccdycujqpMAV8EBRZGxqSf74sBQhg9+tzV
0k2oALfV0CznOX3Fn1QEl3d3f3eNe5O1e7VipKBTGz9CGfTE2MIS3cnYU2g3LtoD
55sKjXXnUIPRy7YCCK8Rsd/bZITJMX6A5FhBpyuMl0szTf5XI4p/hBW/S9lOiGBc
AATL+jctjXz7bj6PjCvEBlINXct5h3u7xoL6wNxx9lRayEWRaManYczhXsy9ZaFU
2TUQYFSN5VTJVIQ8X2Uaip+uPimikdrXImOA51FAUri5esJceuVB
Key-Derivation: Argon2id
Argon2-Memory: 8192
Argon2-Passes: 34
Argon2-Parallelism: 1
Argon2-Salt: 8cc26a979c9bde54fbc3fcb4e04734eb
Private-Lines: 14
svCLtLXDHcRYZRhwDP+9/VZu8gw7EY5ONC/tIZbcQr9JE52fcfPkUt2YHSxptOfB
X9W0wUzryh9pbRULWbQcdP8slfBsfPmMK5REWudTFMqDosvxTSAHwDwCXdgpJnpV
TgrWJ+NROEy4pIETl0o7x1kIo9UQtXkUhavejaRXZm33cltzA6ciZvET7eQRuTbP
qSEW2Ul4h/JFMhadb0PzDUHDXmIIvZV7HqDhE9aBYE0qorMNA/4hWgEMuoKN5CfO
hW9RouYKWJ64hVN4yff9zTMI8hp9C0NgF8aqiJFjUzaIbvyzfhCQ36U7aSg/ELvq
tgk2N1+YWR8bOairpTmew13qOtyMiejl5RszTjwtv6HgMuZIxxjcDBkpnH6IAid/
TrnOemr7caJKuwl13gcjowvNzzDNNqRJo8rAx9iMieqTGUu05m0oCpWHmVjzuffz
m1V0EFF+DUo4mGVzlXvMUb1e0VNOTcCK8yyU7QqsiqEmapGaiKdfRWadLi/KM/+D
e5jxG7NfbpzJiF+nQN/krS+obP7iC4O+OG7Sq3fRWiLVTd68HS2sYFOR5e9Lrpz3
AiGIOV8blsbIn2ZNTIIB8dCFmoYg8N8FNDmzbhp25iBoEWXWLWsmGkY0peTK1XL7
r/CU3S4MqJeVRFawT+llBuq8yohgtr4Mka+OWeEbMC3ko1eRCFlaQSXdvUV2+f+b
KHyNSq0T/6yGv3xFCWP9qwerUswpW0Qr9BjV+wPnAHPc00F/2Q/7UGg3EAHhYH+A
bbn/vX6whhUeetXLIxPQgiM1XEPsEp9EKDmZZNr9BVjDOULgz473UXor4RglTnXC
PWWPcmGKuuBrKHxtbbyYP1Cjoa2CbVQ5E9mutkGIQTe9hnXQZF0XEKGqsJ8M1wQ8
Private-MAC: 6ef2b36c3493d513e8d4bbc9714c1f616320a22a7e453eb298db373e6d7b667f

26
private_nopassphr.ppk Normal file
View File

@@ -0,0 +1,26 @@
PuTTY-User-Key-File-3: ssh-rsa
Encryption: none
Comment: rsa-key-20251222
Public-Lines: 6
AAAAB3NzaC1yc2EAAAADAQABAAABAQCkhl4EpiCvmTBENERzih8VHL4AzDJfm08e
mA+PYg+mWhrM8eZ79zuAdy6NJHlyP0ccdycujqpMAV8EBRZGxqSf74sBQhg9+tzV
0k2oALfV0CznOX3Fn1QEl3d3f3eNe5O1e7VipKBTGz9CGfTE2MIS3cnYU2g3LtoD
55sKjXXnUIPRy7YCCK8Rsd/bZITJMX6A5FhBpyuMl0szTf5XI4p/hBW/S9lOiGBc
AATL+jctjXz7bj6PjCvEBlINXct5h3u7xoL6wNxx9lRayEWRaManYczhXsy9ZaFU
2TUQYFSN5VTJVIQ8X2Uaip+uPimikdrXImOA51FAUri5esJceuVB
Private-Lines: 14
AAABAEW3doGrz+/5Dv3n1BXNsqwkmNMHtFTVICrLrtRIbm9EgVTVMKDZPAqM9lny
2c+yxrRmPWE6LSm17whqC22EYWAwhovK8TDaa9fjnOqTG1NsOorkzsn+YQDtGj+1
8PgwJIBj4pHhRtrQkfa1vwXnAB40g4K6nU+8979t1kIbfZm905+esCE2i384U4HZ
EdxxqJjiT/qSyWJzCocqdEc7/u8wQbbBJa2ES9i/ABh94o0/Yn2Ub8hknIYKCte2
zzlGlLHQ1r5JxkXEWQhEanv4YX7cmr3KIpz5KZLWm1M/0iD83Ih9mUe8pfLYBMWM
Ey04F+vtXOKkmWho3+9BipepJREAAACBAM1w11la3UhGujE/bxDwdawUPiC5lZaN
4MdsdQ4aAsEMFabRpdR8ZIL4QEIZw73+NEAOiBcc7OpiylMO5Areya4lZ2FPE39e
T0Z/fyqlvYGzSYg4L8f10r56uhwbhsSJRGdrRJfgukHNVjqi14MCN78Ujn/DbjdD
JYpJleAKaS1NAAAAgQDNA772ganZ1rjvmwEGLCBbFtQGDuf6/iMyuAGWObb8zdea
76ZwWtZ3DFotSD/K6ajBzCzH7ghJ9L1URjl0pTJb4Gq5Eel61maaG0ijJ02ZMmQL
vme8Hs7h95J2XcVHaF7DVpNlY/hFXiEyVsVTKWD3LDKhLNM1nbD2WiAafqatxQAA
AIEAp/ot6RXzIHO9o8dfXibt/HPgz3Ulq9jLEUiMHT7oamXyvqDfdFC4QBwxGwnX
J7bzDV2FdwLv3Jsv+s90vnQiHf1/wzW9msT7wyyp1FCV8kQaVwcGEC6Ie1ihh3vN
gZ86hvEdbYMvFIRCheMjoTAJ9BywKQjlq2xaJ8wNGYyunKA=
Private-MAC: 8fb0374e7e484491cc9a5bc9b649605a7f9da3a8e07580b0c6b60dd6464569f6

9
public_Rogers1! Normal file
View File

@@ -0,0 +1,9 @@
---- BEGIN SSH2 PUBLIC KEY ----
Comment: "rsa-key-20251222"
AAAAB3NzaC1yc2EAAAADAQABAAABAQCkhl4EpiCvmTBENERzih8VHL4AzDJfm08e
mA+PYg+mWhrM8eZ79zuAdy6NJHlyP0ccdycujqpMAV8EBRZGxqSf74sBQhg9+tzV
0k2oALfV0CznOX3Fn1QEl3d3f3eNe5O1e7VipKBTGz9CGfTE2MIS3cnYU2g3LtoD
55sKjXXnUIPRy7YCCK8Rsd/bZITJMX6A5FhBpyuMl0szTf5XI4p/hBW/S9lOiGBc
AATL+jctjXz7bj6PjCvEBlINXct5h3u7xoL6wNxx9lRayEWRaManYczhXsy9ZaFU
2TUQYFSN5VTJVIQ8X2Uaip+uPimikdrXImOA51FAUri5esJceuVB
---- END SSH2 PUBLIC KEY ----

BIN
test.xlsx Executable file

Binary file not shown.

193
xsip.cs Executable file
View File

@@ -0,0 +1,193 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
class Program
{
static void Main(string[] args)
{
string sampleHtml = @"
<html>
<head>
<title>Insis Revenue</title>
<link rel=""stylesheet"" type=""text/css"" href=""../Images/OutputStyle.css"" />
<link rel=""stylesheet"" type=""text/css"" href=""../Images/TopHeadingStyle.css"" />
<script type=""text/javascript"" language=""javascript"" src=""../Includes/HighLightRow.js""></script>
</head>
<body onload = ""init()"";>
<div id=""container"">
<div id=""rogersheader""><center><font class=""header"">Revenue Details (<font class='name'>SSCGPAS001</font>)</font></center></div>
</div>
<center>
<form name=""myForm"" method =""post"" action="""">
<div align=""right"">
<font color=""#B22222""><b>Revision:</b>&nbsp;</font>
<select name=""revision"" class =""entry"" onchange =""revisionOnChange()"";>
<option value=""03"">03&nbsp;&nbsp;&nbsp;NS&nbsp;&nbsp;&nbsp;7/31/2025&nbsp;&nbsp;&nbsp;APPR</option>
<option value=""02"">02&nbsp;&nbsp;&nbsp;NS&nbsp;&nbsp;&nbsp;7/31/2025&nbsp;&nbsp;&nbsp;ARCH</option>
<option value=""01"">01&nbsp;&nbsp;&nbsp;NS&nbsp;&nbsp;&nbsp;7/31/2024&nbsp;&nbsp;&nbsp;ARCH</option>
</select>
</div>
<br />
<table class=""normal"" border=""1"" cellspacing=""0"" cellpadding=""0"">
<tr>
<td>
<table class=""line"" cellspacing=""0"" cellpadding=""6"">
<tr class=""heading2"">
<td class=""heading2"">Item</td>
<td class=""heading2"">Code</td>
<td class=""heading2"">Description</td>
<td class=""heading2"">Period</td>
<td class=""heading2"" align=""right"">Unit Price</td>
<td class=""heading2"" align=""center"">Qty</td>
<td class=""heading2"" align=""right"">Amount</td>
<td class=""heading2"" align=""center"">Billing Type</td>
<td class=""heading2"" align=""center"">Currency</td>
</tr>
<tr id=""R0"" onclick=""Highlight_Row(R0)"">
<td nowrap=""nowrap"">01 &nbsp;</td>
<td nowrap=""nowrap"">ACH&nbsp;</td>
<td nowrap=""nowrap"">100M Ethernet Fiber Access-BRE&nbsp;</td>
<td nowrap=""nowrap"">Monthly&nbsp;</td>
<td nowrap=""nowrap"" align=""right"">$200.00&nbsp;</td>
<td nowrap=""nowrap"" align=""center"">1&nbsp;</td>
<td nowrap=""nowrap"" align=""right"">$200.00&nbsp;</td>
<td nowrap=""nowrap"" align=""center""> &nbsp;</td>
<td nowrap=""nowrap"" align=""center"">CD&nbsp;</td>
</tr>
<tr id=""R1"" onclick=""Highlight_Row(R1)"">
<td nowrap=""nowrap"">04 &nbsp;</td>
<td nowrap=""nowrap"">VSS&nbsp;</td>
<td nowrap=""nowrap"">Voice Session Service-BRE &nbsp;</td>
<td nowrap=""nowrap"">Monthly&nbsp;</td>
<td nowrap=""nowrap"" align=""right"">$9.80&nbsp;</td>
<td nowrap=""nowrap"" align=""center"">14&nbsp;</td>
<td nowrap=""nowrap"" align=""right"">$137.20&nbsp;</td>
<td nowrap=""nowrap"" align=""center""> &nbsp;</td>
<td nowrap=""nowrap"" align=""center"">CD&nbsp;</td>
</tr>
</table>
</td>
</tr>
</table>
</form>
</center>
<script type=""text/javascript"" language =""javascript"">
function init() {
myForm.revision.value = ""03""
}
function revisionOnChange(){
window.location.href=""revenue.asp?serv_id=SSCGPAS001&revision="" + myForm.revision.value
}
</script>
<p></p>
<center>
<input class=""button2"" type=""button"" onclick=""top.close()"" value=""Close"" title=""Close"" />
</center>
</body>
</html>";
List<TableDataExtractor.RowData> data = TableDataExtractor.ExtractSpecificTableData(sampleHtml);
foreach (var row in data)
{
Console.WriteLine(row.ToString());
}
}
}
public class TableDataExtractor
{
// A class to hold the extracted data for a single row
public class RowData
{
public string Item { get; set; }
public string Code { get; set; }
public string Description { get; set; }
public string Period { get; set; }
public string UnitPrice { get; set; }
public string Qty { get; set; }
public string Amount { get; set; }
public string BillingType { get; set; }
public string Currency { get; set; }
public override string ToString()
{
return $"Item: {Item}, Description: {Description}, Unit Price: {UnitPrice}, Qty: {Qty}, Amount: {Amount}";
}
}
public static List<RowData> ExtractSpecificTableData(string htmlContent)
{
var extractedData = new List<RowData>();
// Regex to find table rows (<tr>) within a specific table structure (adjust if needed, e.g., using a table ID)
// The pattern uses capturing groups for each <td> content
// It assumes <td> tags might have extra spaces or attributes, but the content inside is the target.
// It specifically looks for rows with exactly 5 data cells.
string rowPattern = @"<tr\s*[^>]*?\bid=[^>]*?>(.*?)</tr\s*>"; //@"<tr\s*[^>]*>(.*?)</tr\s*>";
string cellPattern = @"<td\s*[^>]*>(.*?)</td>";
// Find all rows in the HTML
MatchCollection rows = Regex.Matches(htmlContent, rowPattern, RegexOptions.Singleline | RegexOptions.IgnoreCase);
foreach (Match rowMatch in rows)
{
string rowHtml = rowMatch.Groups[1].Value;
// Find all cells in the current row
MatchCollection cells = Regex.Matches(rowHtml, cellPattern, RegexOptions.Singleline | RegexOptions.IgnoreCase);
// Check if the row has exactly 5 columns of data (Item, Description, Unit Price, Qty, Amount)
if (cells.Count >= 9)
{
// Extract the inner text and clean up whitespace
string item = cells[0].Groups[1].Value.Replace("&nbsp;", " ").Trim();
string code = cells[1].Groups[1].Value.Replace("&nbsp;", " ").Trim();
string description = cells[2].Groups[1].Value.Replace("&nbsp;", " ").Trim();
string period = cells[3].Groups[1].Value.Replace("&nbsp;", " ").Trim();
string unitPrice = cells[4].Groups[1].Value.Replace("&nbsp;", " ").Trim();
string qty = cells[5].Groups[1].Value.Replace("&nbsp;", " ").Trim();
string amount = cells[6].Groups[1].Value.Replace("&nbsp;", " ").Trim();
string billingType = cells[7].Groups[1].Value.Replace("&nbsp;", " ").Trim();
string currency = cells[8].Groups[1].Value.Replace("&nbsp;", " ").Trim();
// Add to the list
extractedData.Add(new RowData
{
Item = item,
Code = code,
Description = description,
Period = period,
UnitPrice = unitPrice,
Qty = qty,
Amount = amount,
BillingType = billingType,
Currency = currency
});
}
}
return extractedData;
}
}

BIN
xsip.exe Executable file

Binary file not shown.