Generates an Excel worksheet with the latest transactions for all depots. The list is in reverse chronological order so the most recent activity in the repository is shown on top. Change FileName and FileLocation in LatestTransactions.exe.config
to specify the name and location of the resultant Excel file. FileLocation must be an existing folder with read/write access privileges. The program uses MS Office interop so Excel must be installed. [Tested with Excel 2010.]
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;
namespace LatestTransactions
{
class Program
{
#region class variables
private static List<string> _depots;
private static List<XElement> _transactions;
private static string _fileName;
private static string _fileLocation;
private static readonly object _locker = new object();
#endregion
[STAThread]
static int Main(string[] args)
{
if (!init()) return 1;
_transactions = new List<XElement>(_depots.Count);
if (initTransListAsync().Result == false) return 1;
return report() ? 0 : 1;
}
private static async Task<bool> initTransListAsync()
{
List<Task<bool>> tasks = new List<Task<bool>>(_depots.Count);
foreach (
string depot in _depots)
tasks.Add(initLastTransAsync(depot));
bool[] arr = await Task.WhenAll(tasks);
return (arr != null && arr.All(n => n == true));
}
private async static Task<bool> initLastTransAsync(string depot)
{
bool ret = false;
try
{
AcResult r = await AcCommand.runAsync($@"hist -p ""{depot}"" -t now -fx");
if (r != null && r.RetVal == 0)
{
XElement xml = XElement.Parse(r.CmdResult);
XElement trans = xml.Element("transaction");
trans.AddAnnotation(depot);
lock (_locker) { _transactions.Add(trans); }
ret = true;
}
}
catch (AcUtilsException exc)
{
AcDebug.Log($"AcUtilsException caught and logged in Program.initLastTransAsync{Environment.NewLine}{exc.Message}");
}
catch (Exception ecx)
{
AcDebug.Log($"Exception caught and logged in Program.initLastTransAsync{Environment.NewLine}{ecx.Message}");
}
return ret;
}
private static bool report()
{
Excel.Application excel = new Excel.Application();
if (excel == null)
{
MessageBox.Show("Excel installation not found.", "LatestTransactions",
MessageBoxButtons.OK, MessageBoxIcon.Hand);
return false;
}
bool ret = true;
excel.DisplayAlerts = false;
Excel.Workbook wbook = excel.Workbooks.Add();
Excel.Worksheet wsheet = (Excel.Worksheet)wbook.Worksheets.get_Item(1);
Excel.Range rheader = wsheet.get_Range("A1", "F1");
rheader.Font.Bold = true;
rheader.HorizontalAlignment = Excel.XlHAlign.xlHAlignCenter;
Excel.Range rdate = wsheet.get_Range("B:B");
rdate.NumberFormat = "mmm d, yyyy h:mm:ss am/pm";
Excel.Range rcomment = wsheet.get_Range("F:F");
rcomment.WrapText = true;
wsheet.Cells[1, "A"] = "Depot";
wsheet.Columns["A"].ColumnWidth = 20;
wsheet.Cells[1, "B"] = "Time";
wsheet.Columns["B"].ColumnWidth = 25;
wsheet.Cells[1, "C"] = "Action";
wsheet.Columns["C"].ColumnWidth = 15;
wsheet.Cells[1, "D"] = "User";
wsheet.Columns["D"].ColumnWidth = 15;
wsheet.Cells[1, "E"] = "Trans_ID";
wsheet.Columns["E"].ColumnWidth = 10;
wsheet.Cells[1, "F"] = "Comment";
wsheet.Columns["F"].ColumnWidth = 50;
int row = 2;
foreach (XElement trans in _transactions.OrderByDescending(n => n.acxTime("time")))
{
string depot = trans.Annotation<string>();
int id = (int)trans.Attribute("id");
string action = (string)trans.Attribute("type");
DateTime? time = trans.acxTime("time");
string user = (string)trans.Attribute(
"user");
string comment = trans.acxComment();
wsheet.Cells[row, "A"] = depot;
wsheet.Cells[row, "B"] = time;
wsheet.Cells[row, "C"] = action;
wsheet.Cells[row,
"D"] =
user;
wsheet.Cells[row, "E"] = id;
wsheet.Cells[row, "F"] = comment;
row++;
}
string file = String.Empty;
try
{
file = Path.Combine(_fileLocation, _fileName);
wbook.SaveAs(Filename: file, ReadOnlyRecommended: true);
wbook.Close();
}
catch (COMException exc)
{
AcDebug.Log(exc.Message);
MessageBox.Show(exc.Message);
ret = false;
}
finally { excel.Quit(); }
if (ret)
{
MessageBox.Show($"Latest transactions saved to {file}", "LatestTransactions",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
return ret;
}
private static bool init()
{
if (!AcDebug.initAcLogging())
{
Console.WriteLine("Logging support initialization failed.");
return false;
}
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AcDebug.unhandledException);
Task<string> prncpl = AcQuery.getPrincipalAsync();
if (String.IsNullOrEmpty(prncpl.Result))
{
AcDebug.Log($"Not logged into AccuRev.{Environment.NewLine}Please login and try again.");
return false;
}
if (!initAppConfigData()) return false;
_depots = AcQuery.getDepotNameListAsync().Result;
if (_depots == null) return false;
return true;
}
private static bool initAppConfigData()
{
bool ret = false;
try
{
_fileName = AcQuery.getAppConfigSetting<string>("FileName").Trim();
_fileLocation = AcQuery.getAppConfigSetting<string>("FileLocation").Trim();
ret = true;
}
catch (ConfigurationErrorsException exc)
{
Process currentProcess = Process.GetCurrentProcess();
ProcessModule pm = currentProcess.MainModule;
AcDebug.Log($"Invalid data in {pm.ModuleName}.config{Environment.NewLine}{exc.Message}");
}
return ret;
}
}
}