152 lines
5.5 KiB
C#
152 lines
5.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Data;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using Spire.Xls;
|
|
|
|
namespace bdf
|
|
{
|
|
class CXLFile
|
|
{
|
|
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) //todo should this be filtered instead?
|
|
{
|
|
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); //todo open up file and verify so version from internals?
|
|
}
|
|
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();
|
|
}
|
|
}
|
|
}
|