Files
SourceCode/PROMS/Volian.Controls.Library/DisplayReports.cs
T

1367 lines
43 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using VEPROMS.CSLA.Library;
using DevComponents.DotNetBar;
using DevComponents.AdvTree;
using Volian.Base.Library;
namespace Volian.Controls.Library
{
public partial class DisplayReports : UserControl
{
#region Public Events/Handlers
public event DisplayReportsEvent PrintRequest;
private void OnPrintRequest(DisplayReportsEventArgs args)
{
PrintRequest?.Invoke(this, args);
}
#endregion
#region Fields
// B2022-026 RO Memeory reduction logic change - defined dummy node text variable to ensure consistancy
private const string DummyNodeText = "VLN_DUMMY_NODE";
#pragma warning disable IDE0044 // Add readonly modifier
private List<DocVersionInfo> lstCheckedDocVersions = new List<DocVersionInfo>();
private List<object> lstCheckedROs = new List<object>();
private List<string> ROList = new List<string>();
#pragma warning restore IDE0044 // Add readonly modifier
private int _MyRODbID;
private DocVersionInfo _MyDocVersion;
private ROFSTLookup _MyROFSTLookup;
private ItemInfoList _ReportResult;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0044:Add readonly modifier", Justification = "Keeping Collections Not ReadOnly")]
private Dictionary<string, string> AccIDROIDdic = new Dictionary<string, string>();
static int blankKeyCnt = 0;
#endregion
#region Properties
private string DocVersionList
{
get
{
// append list of document versions to search
if (lstCheckedDocVersions.Count > 0)
{
string strRtnStr = "";
// get list of doc versions to search
foreach (DocVersionInfo dvi in lstCheckedDocVersions)
{
strRtnStr += string.Format(",{0}", dvi.VersionID.ToString());
}
return strRtnStr.Substring(1);
}
return "";
}
}
public DocVersionInfo Mydocversion
{
get { return _MyDocVersion; }
set
{
if (DesignMode) return; // B2019-043 need to check if we are just saving changes to the user interface
_MyDocVersion = value;
if (_MyDocVersion != null)
{
if (_MyDocVersion.DocVersionAssociationCount > 0)
{
// if the count variable is not consistent with the actual list count,
// do a refresh. There was a bug, B2012-040, that was not reproducable..
// so this is an attempt to fix it.
if (_MyDocVersion.DocVersionAssociations.Count == 0)
{
_MyDocVersion.RefreshDocVersionAssociations();
if (_MyDocVersion.DocVersionAssociations.Count == 0) return;
}
MyROFSTLookup = _MyDocVersion.DocVersionAssociations[0].MyROFst.GetROFSTLookup(_MyDocVersion);
_MyRODbID = _MyDocVersion.DocVersionAssociations[0].MyROFst.RODbID;
}
}
}
}
public ROFSTLookup MyROFSTLookup
{
get { return _MyROFSTLookup; }
set
{
if (DesignMode) return; // B2019-043 need to check if we are just saving changes to the user interface
_MyROFSTLookup = value; // define the tree nodes based on this rofst
advTreeROFillIn();
}
}
public ItemInfoList ReportResult
{
get { return _ReportResult; }
set
{
_ReportResult = value;
}
}
#endregion
#region Constructors
public DisplayReports()
{
InitializeComponent();
EnableOrDisablePrintButton();
cmbxROUsageSort.SelectedIndex = 0;
tabTransitionReports.Visible = false;
cbxComplete.Enabled = true;
cbxSummary.Enabled = true;
if (cbxROUsage.Checked)
cbxIncldMissingROs.Text = "Include Missing ROs (red ? in the editor)";
else if (cbxComplete.Checked)
cbxIncldMissingROs.Text = "Include Empty RO Fields";
cbxIncldMissingROs.Checked = false;// !cbxSummary.Checked;
cbxIncldMissingROs.Visible = cbxROUsage.Checked || cbxComplete.Checked;
cbxSortBySetpointID.Checked = false;
cbxSortBySetpointID.Visible = cbxComplete.Checked || cbxSummary.Checked;
}
#endregion
#region Public Methods
public void SelectReferencedObjectTab()
{
tabROReports.PerformClick();
}
public void advTreeROFillIn()
{
DevComponents.AdvTree.Node topnode = null;
advTreeRO.Nodes.Clear();
if (_MyROFSTLookup == null) return;
advTreeRO.BeforeExpand -= new AdvTreeNodeCancelEventHandler(advTreeRO_BeforeExpand);
advTreeRO.BeforeExpand += new AdvTreeNodeCancelEventHandler(advTreeRO_BeforeExpand);
advTreeRO.AfterExpand -= new AdvTreeNodeEventHandler(advTreeRO_AfterExpandorCollapse);
advTreeRO.AfterExpand += new AdvTreeNodeEventHandler(advTreeRO_AfterExpandorCollapse);
advTreeRO.AfterCollapse -= new AdvTreeNodeEventHandler(advTreeRO_AfterExpandorCollapse);
advTreeRO.AfterCollapse += new AdvTreeNodeEventHandler(advTreeRO_AfterExpandorCollapse);
topnode = new DevComponents.AdvTree.Node
{
Text = "All Referenced Objects",
Tag = null,
CheckBoxVisible = true
};
advTreeRO.Nodes.Add(topnode);
ROFSTLookup.rodbi[] dbs = _MyROFSTLookup.GetRODatabaseList(true);
if (dbs != null && dbs.Length > 0)
{
for (int i = 0; i < dbs.Length; i++)
{
DevComponents.AdvTree.Node tn = new DevComponents.AdvTree.Node();
ROFSTLookup.rodbi db = dbs[i];
tn.Text = db.dbiTitle;
tn.Tag = db;
tn.CheckBoxVisible = true;
topnode.Nodes.Add(tn);
AddDummyGroup(db, tn);
}
}
}
public void advTreeProcSetsFillIn()
{
DevComponents.AdvTree.Node topnode = null;
int cntnd = 0;
VETreeNode vtn = VETreeNode.GetFolder(1);
FolderInfo fi = vtn.VEObject as FolderInfo;
int fiCount = fi.ChildFolderCount;
advTreeProcSets.Nodes.Clear();
lstCheckedDocVersions.Clear();
topnode = new DevComponents.AdvTree.Node
{
Text = "Available Procedure Sets",
Tag = fi
};
advTreeProcSets.Nodes.Add(topnode);
foreach (FolderInfo fic in fi.SortedChildFolders)
{
DevComponents.AdvTree.Node newnode = new DevComponents.AdvTree.Node
{
Text = fic.ToString(),
Tag = fic
};
cntnd++;
if (fic.ChildFolderCount > 0 || fic.FolderDocVersionCount > 0) // allow for '+' for tree expansion
{
DevComponents.AdvTree.Node tnt = new DevComponents.AdvTree.Node
{
Text = DummyNodeText
};
newnode.Nodes.Add(tnt);
topnode.Nodes.Add(newnode);
}
}
// if nothing was added to the tree, just put in the node above the docversions...
if (advTreeProcSets.Nodes.Count == 0)
{
cntnd++;
fi = Mydocversion.MyFolder;
topnode = new DevComponents.AdvTree.Node
{
Text = fi.ToString()
};
advTreeProcSets.Nodes.Add(topnode);
topnode.Tag = fi;
}
advTreeProcSets.BeforeExpand -= new DevComponents.AdvTree.AdvTreeNodeCancelEventHandler(advTreeProcSets_BeforeExpand);
advTreeProcSets.BeforeExpand += new DevComponents.AdvTree.AdvTreeNodeCancelEventHandler(advTreeProcSets_BeforeExpand);
// position to the procedure set in the tree if we have a procedure open
if (Mydocversion != null)
advTreeProcSetsPreSelect();
else
advTreeProcSets.Nodes[0].SelectedCell = advTreeProcSets.Nodes[0].Cells[0]; // select the first node - fixes cosmetic problem
}
#endregion
#region Private Methods
private void GenerateAccIDSortedROList()
{
List<string> AccPgIDsList = new List<string>();
AccIDROIDdic.Clear();
ROFSTLookup.rochild ch;
ROList.Clear();
foreach (object rolkup in lstCheckedROs)
{
if (rolkup == null) // All Referenced Objects selected, return list of RO databases
{
foreach (ROFSTLookup.rodbi rodbi in _MyROFSTLookup.GetRODatabaseList(true))
{
string rtnStr = $"{_MyRODbID}:{string.Format("{0}", rodbi.dbiID.ToString("X4"))}";
if (rodbi.children != null)
{
foreach (ROFSTLookup.rochild roc in rodbi.children)
{
PutROChildrenInDictionary(_MyRODbID.ToString() + ":", roc);
}
}
else
{
ROList.Add(rtnStr);
}
}
continue;
}
else if (rolkup is ROFSTLookup.rodbi rodbi)
{
//Try to lazy load the children - B2022-026 RO Memory Reduction code
if (rodbi.children == null || rodbi.children.Length <= 0)
rodbi.children = MyROFSTLookup.GetRoChildrenByID(rodbi.ID, rodbi.dbiID, true);
if (rodbi.children != null)
{
foreach (ROFSTLookup.rochild roc in rodbi.children)
{
PutROChildrenInDictionary(_MyRODbID.ToString() + ":", roc);
}
}
else
{
ROList.Add($"{_MyRODbID}:{string.Format("{0}", rodbi.dbiID.ToString("X4"))}");
}
}
else if (rolkup is ROFSTLookup.rochild rochild)
{
ch = rochild;
ROFSTLookup.rochild[] chld = ch.children;
//Try to lazy load the children - B2022-026 RO Memory Reduction code
if (ch.children == null || ch.children.Length <= 0)
ch.children = MyROFSTLookup.GetRoChildrenByRoid(ch.roid, true);
PutROChildrenInDictionary(_MyRODbID.ToString() + ":", rolkup);
}
}
foreach (string k in AccIDROIDdic.Keys)
{
AccPgIDsList.Add(k);
}
string[] AccPgIdListArray = AccPgIDsList.ToArray();
Array.Sort(AccPgIdListArray, new AlphanumComparatorFast());
foreach (string accid in AccPgIdListArray)
{
ROList.Add(AccIDROIDdic[accid]);
}
}
private string GetNextBlankKey()
{
return string.Format(" _{0}", blankKeyCnt++);
}
private void PutROChildrenInDictionary(string rodbidPrefix, object roObj)
{
ROFSTLookup.rochild chld = (ROFSTLookup.rochild)roObj;
string keystr = ((chld.appid == "") ? GetNextBlankKey() : chld.appid) + chld.roid.Substring(0, 4);
//Try to lazy load the children - B2022-026 RO Memory Reduction
if (chld.children == null || chld.children.Length <= 0)
chld.children = MyROFSTLookup.GetRoChildrenByRoid(chld.roid, true);
string rtnstr;
// If still no children - B2022-026 RO Memory Reduction code - check children length
if (chld.children == null || chld.children.Length <= 0) // get a single ROID
{
rtnstr = rodbidPrefix + string.Format("{0}", chld.roid);
if (rtnstr.Length == 12) rtnstr += "0000"; // last four digits are used for multiple return values
// B2023-094: Don't crash when trying to add another ro if it has same key. Note that this is coming in as an RO but is really a group.
if (!AccIDROIDdic.ContainsKey(keystr)) AccIDROIDdic.Add(keystr, rtnstr);
}
else if (!cbxROUsage.Checked && chld.children[0].ParentID == 0)
{
rtnstr = rodbidPrefix + string.Format("{0},", chld.roid); // doing a RO Summary or RO Complete report - don't want children that are multiple return values
AccIDROIDdic.Add(keystr, rtnstr);
}
else
{
// spin through the child list and get the ROIDs.
// if the child has children, then call this function recursively
for (int i = 0; i < chld.children.Length; i++)
{
ROFSTLookup.rochild roc = chld.children[i];
//Try to lazy load the children - B2022-026 RO Memory Reduction code
if (roc.children == null || roc.children.Length <= 0)
roc.children = MyROFSTLookup.GetRoChildrenByRoid(roc.roid, true);
// Don't get the children if we are doing a RO Summary or RO Complete report & children are the multiple return values
if (roc.children != null && roc.children.Length > 0 && (cbxROUsage.Checked || roc.children[0].ParentID != 0))
{
PutROChildrenInDictionary(rodbidPrefix, roc);
}
else if (roc.appid != null && roc.appid != "")
{
rtnstr = rodbidPrefix + string.Format("{0}", roc.roid);
keystr = ((roc.appid == "") ? GetNextBlankKey() : roc.appid) + chld.roid.Substring(0, 4);
if (AccIDROIDdic.ContainsKey(keystr)) // For duplicates, append the parent title (B2017-011) so adding to dictionary doesn't crash.
{
keystr = $"{keystr}|{chld.title}";
}
AccIDROIDdic.Add(keystr, rtnstr);
}
}
}
}
private void GenerateROList()
{
string rtnStr = "";
ROFSTLookup.rochild ch;
ROList.Clear();
foreach (object rolkup in lstCheckedROs)
{
if (rolkup == null) // All Referenced Objects selected, return list of RO databases
{
// B2022-026 RO Memory Reduction code - added flag to load all children
foreach (ROFSTLookup.rodbi rodbi in _MyROFSTLookup.GetRODatabaseList(true))
{
rtnStr = $"{_MyRODbID}:{string.Format("{0}", rodbi.dbiID.ToString("X4"))}";
ROList.Add(rtnStr);
}
continue;
}
else if (rolkup is ROFSTLookup.rodbi rodbi)
{
rtnStr = $"{_MyRODbID}:{string.Format("{0}", rodbi.dbiID.ToString("X4"))}";
}
else if (rolkup is ROFSTLookup.rochild rochild)
{
ch = rochild;
//Try to lazy load the children - B2022-026 RO Memory Reduction code
if (ch.children == null || ch.children.Length <= 0)
ch.children = MyROFSTLookup.GetRoChildrenByRoid(ch.roid, true);
ROFSTLookup.rochild[] chld = ch.children;
rtnStr = $"{_MyRODbID}:{GetROChildren(rolkup).TrimEnd(',')}"; // GetROChildren(rolkup).TrimEnd(',') grabs the children of the selected item
}
ROList.Add(rtnStr);
}
}
// same function as GetROsToSearch in DisplaySearch.cs
private string GetROChildren(object roObj)
{
ROFSTLookup.rochild chld = (ROFSTLookup.rochild)roObj;
string rtnstr = "";
//Try to lazy load the children - B2022-026 RO Memory Reduction code
if (chld.children == null || chld.children.Length <= 0)
chld.children = MyROFSTLookup.GetRoChildrenByRoid(chld.roid, true);
// If still no children
if (chld.children == null || chld.children.Length <= 0) // get a single ROID
{
rtnstr += string.Format("{0}", chld.roid);
if (rtnstr.Length == 12) rtnstr += "0000"; // last four digits are used for multiple return values
}
else if (!cbxROUsage.Checked && chld.children[0].ParentID == 0)
{
rtnstr += string.Format("{0},", chld.roid); // doing a RO Summary or RO Complete report - don't want children that are multiple return values
}
else
{ // spin through the child list and get the ROIDs.
// if the child has children, then call this function recursivly
foreach (ROFSTLookup.rochild roc in chld.children)
{
// Don't get the children if we are doing a RO Summary or RO Complete report & children are the multiple return values
// B2022-062: Proms crashes on Complete or Summary RO report without 'Sort by SetpointID'. With new ROfst logic,
// need to check for children length > 0 also.
if (roc.children != null && roc.children.Length > 0 && (cbxROUsage.Checked || roc.children[0].ParentID != 0))
rtnstr += GetROChildren(roc);
else
rtnstr += string.Format("{0},", roc.roid);
}
}
return rtnstr;
}
private string GetListOfROs(bool keepRODbID)
{
string rtnStr = "";
string strRODbID = "";
int cnt = 0;
foreach (string rostr in ROList)
{
int ndxOf = rostr.IndexOf(":");
if (ndxOf > 0)
{
string tstr = rostr.Substring(0, ndxOf + 1);
if (tstr != strRODbID && keepRODbID)
{
strRODbID = tstr;
rtnStr += rostr;
}
else
rtnStr += rostr.Substring(ndxOf + 1);
}
else
rtnStr += rostr;
if (rtnStr.EndsWith(",")) rtnStr = rtnStr.Substring(0, rtnStr.Length - 1);
if (++cnt < ROList.Count)
rtnStr += ",";
}
return rtnStr;
}
private void AddSelectedROChildren(DevComponents.AdvTree.NodeCollection chldrn)
{
if (chldrn.Count > 0)
{
foreach (DevComponents.AdvTree.Node n in chldrn)
{
if (n.Checked)
lstCheckedROs.Add(n.Tag);
else
AddSelectedROChildren(n.Nodes);
}
}
}
private void BuildCheckedROsList()
{
lstCheckedROs.Clear();
if (advTreeRO.Nodes.Count == 0) return;
DevComponents.AdvTree.Node node = advTreeRO.Nodes[0];
if (node.Checked) // top node (all Referenced Objects) selected
lstCheckedROs.Add(node.Tag);
else
AddSelectedROChildren(node.Nodes);
}
private void EnableOrDisablePrintButton()
{
switch (tctrlReports.SelectedTabIndex)
{
case 0: // Transition Reports
btnPrintReport.Enabled = (lstCheckedDocVersions.Count > 0);
break;
case 1: // Referenced Objects Reports
BuildCheckedROsList(); // this list is sent to the report generator
if (cbxROUsage.Checked)
btnPrintReport.Enabled = (lstCheckedDocVersions.Count > 0 && lstCheckedROs.Count > 0);
else
btnPrintReport.Enabled = ((cbxComplete.Checked || cbxSummary.Checked) && lstCheckedROs.Count > 0);
break;
}
if (cbxROUsage.Checked)
cbxIncldMissingROs.Text = "Include Missing ROs (red ? in the editor)";
else if (cbxComplete.Checked)
cbxIncldMissingROs.Text = "Include Empty RO Fields";
//cbxIncldMissingROs.Checked = cbxROUsage.Checked || cbxComplete.Checked;
cbxIncldMissingROs.Visible = cbxROUsage.Checked || cbxComplete.Checked;
cbxSortBySetpointID.Visible = cbxComplete.Checked || cbxSummary.Checked;
labelX1.Visible = cmbxROUsageSort.Visible = !cbxSortBySetpointID.Visible;
}
private void tabTransitionReports_Click(object sender, EventArgs e)
{
xpSetToReport.Enabled = true;
xpSetToReport.Expanded = true;
xpSelROs.Expanded = false;
xpSelROs.Enabled = false;
EnableOrDisablePrintButton();
}
private void tabROReports_Click(object sender, EventArgs e)
{
xpSetToReport.Enabled = cbxROUsage.Checked;
xpSetToReport.Expanded = cbxROUsage.Checked;
labelX1.Visible = cmbxROUsageSort.Visible = cbxROUsage.Checked;
xpSelROs.Enabled = true;
xpSelROs.Expanded = true;
cbxIncldMissingROs.Checked = false;// !cbxSummary.Checked;
cbxSortBySetpointID.Checked = false;
cbxSortBySetpointID.Visible = !cbxROUsage.Checked;
EnableOrDisablePrintButton();
}
private void cbxROUsage_CheckedChanged(object sender, EventArgs e)
{
xpSetToReport.Enabled = cbxROUsage.Checked;
xpSetToReport.Expanded = cbxROUsage.Checked;
labelX1.Visible = cmbxROUsageSort.Visible = cbxROUsage.Checked;
// reset the RO tree and clear anything that was selected
advTreeROFillIn();
lstCheckedROs.Clear();
cbxIncldMissingROs.Checked = false;// !cbxSummary.Checked;
cbxSortBySetpointID.Checked = false;
cbxSortBySetpointID.Visible = !cbxROUsage.Checked;
EnableOrDisablePrintButton();
}
private void DisplayReports_Load(object sender, EventArgs e)
{
tabTransitionReports.PerformClick();
}
// when a node is checked (selected) then uncheck any of its children
private void UncheckChildren(DevComponents.AdvTree.NodeCollection chldrn)
{
if (chldrn.Count > 0)
{
foreach (DevComponents.AdvTree.Node n in chldrn)
{
if (n.Checked)
n.Checked = false;
else
UncheckChildren(n.Nodes);
}
}
}
// when a node is checked (selected), uncheck the parents, grand parents, great grand parents, etc.
private void UncheckParents(DevComponents.AdvTree.Node pNode)
{
while (pNode != null)
{
if (pNode.Checked) pNode.Checked = false;
pNode = pNode.Parent;
}
}
private void advTreeRO_AfterCheck(object sender, AdvTreeCellEventArgs e)
{
DevComponents.AdvTree.Node n = advTreeRO.SelectedNode;
if (n.Checked)
{
UncheckChildren(n.Nodes);
UncheckParents(n.Parent);
}
EnableOrDisablePrintButton();
}
private void cbxTransToProcs_CheckedChanged(object sender, EventArgs e)
{
EnableOrDisablePrintButton();
}
private void cbxTransFromProcs_CheckedChanged(object sender, EventArgs e)
{
EnableOrDisablePrintButton();
}
private void cbxComplete_CheckedChanged(object sender, EventArgs e)
{
cbxIncldMissingROs.Checked = false;// !cbxSummary.Checked;
cbxSortBySetpointID.Checked = false;
EnableOrDisablePrintButton();
}
private void cbxSummary_CheckedChanged(object sender, EventArgs e)
{
EnableOrDisablePrintButton();
}
private string BuildRODataFile(string ROList)
{
DocVersionInfo MyDVI = Mydocversion;
string roDataFile = "PRINT.TMP";
if (VlnSettings.ReleaseMode.Equals("DEMO"))
{
MessageBox.Show("Referenced Object Reports not available in the Demo version.", "PROMS Demo Version");
return "";
}
string roapp = Volian.Base.Library.ExeInfo.GetROEditorPath(); // get the path to the RO Editor Executable
if (roapp == null)
{
MessageBox.Show("Could not find path to Ro Editor, check 'roapp' environment variable");
return "";
}
if (MyDVI == null || MyDVI.DocVersionAssociationCount < 1)
{
MessageBox.Show("Could not find associated path for ro data.", "No RO Data", MessageBoxButtons.OK, MessageBoxIcon.Information);
return "";
}
if (!Directory.Exists(MyDVI.DocVersionAssociations[0].MyROFst.MyRODb.FolderPath))
{
MessageBox.Show(string.Format("RO Database directory does not exist: {0}", MyDVI.DocVersionAssociations[0].MyROFst.MyRODb.FolderPath));
return "";
}
string cmpRptExePath = roapp.Substring(0, roapp.LastIndexOf("\\")) + "\\CmpRpt.exe ";
roDataFile = $"{MyDVI.DocVersionAssociations[0].MyROFst.MyRODb.FolderPath}\\{roDataFile}";
try
{
if (File.Exists(roDataFile)) File.Delete(roDataFile);
Application.DoEvents();
string fname = $"{VlnSettings.TemporaryFolder}\\ROCompleteRprt.txt";
FileInfo fi = new FileInfo(fname);
using (StreamWriter sw = fi.CreateText())
{
sw.Write(ROList);
sw.Close();
}
string roloc = $"\"{MyDVI.DocVersionAssociations[0].MyROFst.MyRODb.FolderPath}\" \"/f={fname}\"";
// C2017-003: ro data in sql server, check for sql connection string
if (MyDVI.DocVersionAssociations[0].MyROFst.MyRODb.DBConnectionString != "cstring") roloc = $"{roloc} \"/sql={MyDVI.DocVersionAssociations[0].MyROFst.MyRODb.DBConnectionString}\"";
// C2021-026 pass in Parent/Child information (list of the children)
// B2022-019 look at all DocVersions to find ParentChild information
// to ensure we pass in Parent/Child even when not coming from a Parent/Child procedure set
DocVersionInfoList dvil = DocVersionInfoList.Get();
foreach (DocVersionInfo dvi in dvil)
{
if (dvi.DocVersionConfig is DocVersionConfig dvc && dvc.Unit_Name != "" && dvc.Unit_Count > 1) // B2021-089 only pass in applicability info if defined for more than one unit
roloc += $" \"/PC={dvc.Unit_Name}\"";
break;
}
System.Diagnostics.Process p = System.Diagnostics.Process.Start(cmpRptExePath, roloc);
// need to wait, sometimes the Print.tmp file that is generated is not available
p.WaitForExit(); // without arguments, this will wait indefinitely
Application.DoEvents();
}
catch (Exception ex)
{
while (ex.InnerException != null)
ex = ex.InnerException;
string tmpmsg = ex.Message;
MessageBox.Show(tmpmsg, $"RO Report Error: {ex.GetType().Name}");
}
return roDataFile;
}
private void btnPrintReport_Click(object sender, EventArgs e)
{
string paperSize = "Letter";
if (Mydocversion != null && Mydocversion.ActiveFormat != null)
paperSize = Mydocversion.ActiveFormat.PlantFormat.FormatData.PDFPageSize.PaperSize; // C2020-002 paper size is now set in the format files
//B2019-144 Set the document text color to Red (overlay) or Black (normal)
Color lastColor = MSWordToPDF.OverrideColor;// B2019-144 Remember override color
if (MSWordToPDF.OverrideColor != Color.Black)
MSWordToPDF.OverrideColor = Color.Black;
Cursor curcur = Cursor;
Cursor = Cursors.WaitCursor;
if (cbxSummary.Checked) // RO Summary Report
{
if (cbxSortBySetpointID.Checked)
GenerateAccIDSortedROList();
else
GenerateROList();
OnPrintRequest(new DisplayReportsEventArgs("RO Summary Report", "RO Summary Report", MyROFSTLookup, ROList, paperSize));
}
else if (cbxComplete.Checked) // Complete RO Report
{
if (cbxSortBySetpointID.Checked)
GenerateAccIDSortedROList();
else
GenerateROList();
string ROList = GetListOfROs(false);//don't include the RODbID in the RO list
string roDataFile = BuildRODataFile(ROList);
// B2023-028: RO report generates report with error when RO path not set. Return if datafile is not set
// by BuildRODataFile
if (roDataFile == null || roDataFile == "")
{
Cursor = curcur; // B2023-094: restore cursor (was wait). Not part of bug, found during fix
return;
}
if (Mydocversion != null)
OnPrintRequest(new DisplayReportsEventArgs("Complete RO Report", "Complete RO Report", roDataFile, MyROFSTLookup, cbxComplete.Checked, Mydocversion.ActiveFormat.PlantFormat.FormatData.SectData.ConvertCaretToDelta, cbxIncldMissingROs.Checked, paperSize));
}
else if (cbxROUsage.Checked)
{
bool usageSortedByProcedure = (cmbxROUsageSort.SelectedIndex == 1);
GenerateROList();
string SearchString = GetListOfROs(true);// Include the RODbID in the RO list
ItemInfoList SearchResults = ItemInfoList.GetListFromROReport(DocVersionList, "", SearchString, "");
List<ItemInfo> sortedResults = SearchResults.SortedList(!usageSortedByProcedure);
OnPrintRequest(new DisplayReportsEventArgs("Referenced Objects Usage By RO", "RO Usage", sortedResults, usageSortedByProcedure, cbxIncldMissingROs.Checked, paperSize));
}
else if (cbxTransFromProcs.Checked)
{
}
else if (cbxTransToProcs.Checked)
{
}
Cursor = curcur;
//B2019-144 Set the document text color to Red (overlay) or Black (normal)
if (MSWordToPDF.OverrideColor != lastColor)// B2019-144 Restore override color
MSWordToPDF.OverrideColor = lastColor;
}
#region (Procedure List)
private void advTreeProcSets_BeforeExpand(object sender, DevComponents.AdvTree.AdvTreeNodeCancelEventArgs e)
{
DevComponents.AdvTree.Node par = e.Node;
// get first child's text, if it has one & if the text is "VLN_DUMMY_NODE", load children
DevComponents.AdvTree.Node tn = null;
if (par.Nodes.Count > 0) tn = par.Nodes[0];
if (tn.Text == DummyNodeText) // expand this
{
par.Nodes.Clear();
Object obj = par.Tag;
if (!(obj is FolderInfo)) return; // should always be folderinfo on expand
FolderInfo fi = (FolderInfo)obj;
if (fi.ChildFolderCount > 0)
{
foreach (FolderInfo fic in fi.SortedChildFolders)
{
DevComponents.AdvTree.Node newnode = new DevComponents.AdvTree.Node
{
Text = fic.ToString(),
Tag = fic
};
par.Nodes.Add(newnode);
if (fic.HasChildren) // allow for '+' for tree expansion
{
DevComponents.AdvTree.Node tnt = new DevComponents.AdvTree.Node
{
Text = DummyNodeText
};
newnode.Nodes.Add(tnt);
}
}
}
else if (fi.FolderDocVersionCount > 0)
{
foreach (DocVersionInfo dv in fi.FolderDocVersions)
{
DevComponents.AdvTree.Node newnode = new DevComponents.AdvTree.Node
{
Text = dv.ToString(),
Tag = dv,
Selectable = true,
CheckBoxAlignment = DevComponents.AdvTree.eCellPartAlignment.NearCenter,
CheckBoxStyle = eCheckBoxStyle.CheckBox,
CheckBoxThreeState = false,
CheckBoxVisible = true
};
par.Nodes.Add(newnode);
}
}
}
}
private void advTreeProcSets_AfterCheck(object sender, DevComponents.AdvTree.AdvTreeCellEventArgs e)
{
DevComponents.AdvTree.Node n = advTreeProcSets.SelectedNode;
if (n.Checked)
{
n.Style = DevComponents.AdvTree.NodeStyles.Apple;
lstCheckedDocVersions.Add((DocVersionInfo)n.Tag);
if (lstCheckedDocVersions.Count == 1)//Mydocversion == null)
{
Mydocversion = (DocVersionInfo)n.Tag;
}
}
else
{
n.Style = null;
lstCheckedDocVersions.Remove((DocVersionInfo)n.Tag);
if (lstCheckedDocVersions.Count == 1)
{
if (Mydocversion != lstCheckedDocVersions[0])
{
Mydocversion = lstCheckedDocVersions[0];
}
}
else
{
if (lstCheckedDocVersions.Count == 0)
Mydocversion = null;
}
}
EnableOrDisablePrintButton();
}
private void advTreeProcSets_AfterNodeSelect(object sender, AdvTreeNodeEventArgs e)
{
_ = advTreeProcSets.SelectedNode;
}
private void advTreeProcSetsPreSelect()
{
bool keeplooking = true;
//build a stack (bread crumb trail) of where is procedure set came from within the tree.
Stack<string> crumbs = new Stack<string>();
crumbs.Push(Mydocversion.Name); // ex: "working draft"
crumbs.Push(Mydocversion.MyFolder.Name); // ex: "Emergency Procedures"
FolderInfo fi = Mydocversion.MyFolder.MyParent;
while (fi != null)
{
if (fi.MyParent != null)
crumbs.Push(fi.Name);
fi = fi.MyParent;
}
crumbs.Push(advTreeProcSets.Nodes[0].Text); //top node of my tree
// now walk the tree, looking for the node names we saved in the stack.
NodeCollection monkeys = advTreeProcSets.Nodes;
while (keeplooking)
{
Node climber = LookInTree(monkeys, crumbs.Pop());
keeplooking = (climber != null && crumbs.Count > 0);
if (keeplooking)
monkeys = climber.Nodes;
if (!keeplooking && climber != null)
{
climber.Checked = true;
}
}
}
private Node LookInTree(NodeCollection monkeys, string bananna)
{
Node foundit = null;
foreach (Node chimp in monkeys)
{
if (chimp.Text.Equals(bananna))
{
foundit = chimp;
// need to select the node (cell) for it to be checked
chimp.SelectedCell = chimp.Cells[0];
if (chimp.Nodes.Count > 0)
chimp.Expand();
break;
}
chimp.Collapse();
}
return foundit;
}
#endregion
#region (RO Tree)
private void AddDummyGroup(ROFSTLookup.rodbi rodbi, DevComponents.AdvTree.Node tn)
{
if (rodbi.children != null && rodbi.children.Length > 0)
{
DevComponents.AdvTree.Node tmp = new DevComponents.AdvTree.Node
{
Text = DummyNodeText
};
tn.Nodes.Add(tmp);
}
}
private void advTreeRO_BeforeExpand(object sender, DevComponents.AdvTree.AdvTreeNodeCancelEventArgs e)
{
LoadChildren(e.Node);
}
private void LoadChildren(DevComponents.AdvTree.Node tn)
{
//Check if node has already been loaded
if (tn.HasChildNodes && tn.Nodes[0].Text != DummyNodeText) return; // already loaded.
if (tn.HasChildNodes && tn.Nodes[0].Text == DummyNodeText) tn.Nodes[0].Remove();
ROFSTLookup.rochild[] chld;
if (tn.Tag is ROFSTLookup.rodbi db)
{
//Try to lazy load the children - B2022-026 RO Memory Reduction code
if (db.children == null || db.children.Length <= 0)
db.children = MyROFSTLookup.GetRoChildrenByID(db.ID, db.dbiID, true);
chld = db.children;
}
else if (tn.Tag is ROFSTLookup.rochild ch)
{
//Try to lazy load the children - B2022-026 RO Memory Reduction code
if (ch.children == null || ch.children.Length <= 0)
ch.children = MyROFSTLookup.GetRoChildrenByRoid(ch.roid, true);
chld = ch.children;
}
else
{
Console.WriteLine("error - no type");
return;
}
// if children, add dummy node
// B2022-026 RO Memory Reduction code - check child length
if (chld != null && chld.Length > 0)
{
for (int i = 0; i < chld.Length; i++)
{
// Try to Lazy Load children - B2022-026 RO Memory Reduction code
if (chld[i].children == null || chld[i].children.Length <= 0)
chld[i].children = MyROFSTLookup.GetRoChildrenByRoid(chld[i].roid, true);
Node tmp;
// if this is a group, i.e. type 0, add a dummy node
if (chld[i].type == 0 && chld[i].children == null)
{
// Ignore: Junk Scenario
continue;
}
// B2023-094: don't crash if chld[i].children count is 0, signals an empty group
else if (chld[i].value == null && (cbxROUsage.Checked || (chld[i].children != null && chld[i].children.Length > 0 && chld[i].children[0].ParentID != 0)))
{
tmp = new DevComponents.AdvTree.Node
{
Text = chld[i].title,
Tag = chld[i],
CheckBoxVisible = true
};
int index = FindIndex(tn.Nodes, tmp.Text);
tn.Nodes.Insert(index, tmp);
DevComponents.AdvTree.Node sub = new DevComponents.AdvTree.Node
{
Text = DummyNodeText
};
tmp.Nodes.Add(sub);
}
else
{
tmp = new DevComponents.AdvTree.Node
{
Text = chld[i].title,
Tag = chld[i],
CheckBoxVisible = true
};
int index = FindIndex(tn.Nodes, tmp.Text);
tn.Nodes.Insert(index, tmp);
}
}
}
}
private void advTreeRO_AfterExpandorCollapse(object sender, AdvTreeNodeEventArgs e)
{
Node bottomNode = BottomTreeNode(advTreeRO.Nodes);
_ = advTreeRO.Nodes[advTreeRO.Nodes.Count - 1];
int top = advTreeRO.Nodes[0].Bounds.Top;
int hScrollBarHeight = advTreeRO.HScrollBar != null ? advTreeRO.HScrollBar.Height : 0;
int bottom = bottomNode.Bounds.Bottom + 5;
advTreeRO.Size = new Size(advTreeRO.Size.Width, Math.Min(525, bottom - top + hScrollBarHeight));
if (advTreeRO.VScrollBar != null && bottom < advTreeRO.Size.Height)
{
int yLookFor = (bottom - advTreeRO.Size.Height) + 2 * hScrollBarHeight;
Node topNode = FindTreeNodeAt(advTreeRO.Nodes, yLookFor);
topNode?.EnsureVisible();
}
}
private Node FindTreeNodeAt(NodeCollection nodes, int y)
{
foreach (Node node in nodes)
{
if (node.Bounds.Top <= y && node.Bounds.Bottom >= y)
return node;
if (node.Bounds.Top > y)
{
if (node.PrevNode != null && node.PrevNode.Expanded)
return FindTreeNodeAt(node.PrevNode.Nodes, y);
return node;
}
}
return null;
}
private Node BottomTreeNode(NodeCollection nodes)
{
Node bottomNode = nodes[nodes.Count - 1]; // Return bottom node in collection
if (bottomNode.Expanded) // If expanded return bottom child
return BottomTreeNode(bottomNode.Nodes);
return bottomNode;
}
private int FindIndex(NodeCollection nodes, string value)
{
int index = 0;
foreach (Node node in nodes)
{
if (GreaterValue(node.Text, value)) return index;
index++;
}
return index;
}
private bool GreaterValue(string value1, string value2)
{
return DisplayRO.GreaterValue(value1, value2);
}
#endregion
#endregion
}
#region DisplayReportsEventArgs Class
public class DisplayReportsEventArgs
{
#region Fields
#endregion
#region Properties
public string ReportTitle { get; set; }
public string TypesSelected { get; set; }
public ICollection<ItemInfo> MyItemInfoList { get; set; }
public bool SortUsageByProcedure { get; set; }
public string RODataFile { get; set; } = "";
public bool CompleteROReport { get; set; } = true;
public ROFSTLookup RofstLookup { get; set; }
public List<string> ROListForReport { get; set; }
public bool IncludeMissingROs { get; set; } = true;
public bool ConvertCaretToDelta { get; set; } = true;
public bool IncludeEmptyROFields { get; set; } = true;
public string PaperSize // C2020-002 paper size is now set in the format files
{ get; set; } = "Letter";
#endregion
#region Constructors
/// <summary>
/// RO Usage Report
/// </summary>
/// <param name="reportTitle"></param>
/// <param name="typesSelected"></param>
/// <param name="myItemInfoList"></param>
/// <param name="sortByProcedure"></param>
/// <param name="includeMissingROs"></param>
/// <param name="paperSize"></param>
public DisplayReportsEventArgs(string reportTitle, string typesSelected, ICollection<ItemInfo> myItemInfoList, bool sortByProcedure, bool includeMissingROs, string paperSize)
{
ReportTitle = reportTitle;
TypesSelected = typesSelected;
MyItemInfoList = myItemInfoList;
SortUsageByProcedure = sortByProcedure;
IncludeMissingROs = includeMissingROs;
PaperSize = paperSize; // C2020-002 paper size is now set in the format files
}
/// <summary>
/// RO Complete
/// </summary>
/// <param name="reportTitle"></param>
/// <param name="typesSelected"></param>
/// <param name="roDataFile"></param>
/// <param name="rofstLookUp"></param>
/// <param name="completeROReport"></param>
/// <param name="convertCaretToDelta"></param>
/// <param name="includeEmptyROFields"></param>
/// <param name="paperSize"></param>
public DisplayReportsEventArgs(string reportTitle, string typesSelected, string roDataFile, ROFSTLookup rofstLookUp, bool completeROReport, bool convertCaretToDelta, bool includeEmptyROFields, string paperSize)
{
ReportTitle = reportTitle;
TypesSelected = typesSelected;
RODataFile = roDataFile;
CompleteROReport = completeROReport;
ConvertCaretToDelta = convertCaretToDelta;
RofstLookup = rofstLookUp;
IncludeEmptyROFields = includeEmptyROFields;
PaperSize = paperSize; // C2020-002 paper size is now set in the format files
}
/// <summary>
/// RO Summary Report
/// </summary>
/// <param name="reportTitle"></param>
/// <param name="typesSelected"></param>
/// <param name="rofstLookUp"></param>
/// <param name="roListForReport"></param>
/// <param name="paperSize"></param>
public DisplayReportsEventArgs(string reportTitle, string typesSelected, ROFSTLookup rofstLookUp, List<string> roListForReport, string paperSize)
{
ReportTitle = reportTitle;
TypesSelected = typesSelected;
RofstLookup = rofstLookUp;
ROListForReport = roListForReport;
PaperSize = paperSize; // C2020-002 paper size is now set in the format files
}
#endregion
}
#endregion
public delegate void DisplayReportsEvent(object sender, DisplayReportsEventArgs args);
#region AlphanumComparatorFast Class
public class AlphanumComparatorFast : IComparer<string>
{
#region Public Methods
public List<string> GetList(string s1)
{
List<string> SB1 = new List<string>();
string st1;
st1 = "";
bool flag = char.IsDigit(s1[0]);
foreach (char c in s1)
{
if (flag != char.IsDigit(c) || !(char.IsDigit(c) || char.IsLetter(c)))
{
if (st1 != "")
SB1.Add(st1);
st1 = "";
flag = char.IsDigit(c);
}
if (char.IsDigit(c))
{
st1 += c;
}
if (char.IsLetter(c))
{
st1 += c;
}
}
SB1.Add(st1);
return SB1;
}
public int Compare(string x, string y)
{
string s1 = x;// as string;
if (s1 == null)
{
return 0;
}
string s2 = y;// as string;
if (s2 == null)
{
return 0;
}
if (s1 == s2)
{
return 0;
}
// Walk through two the strings with two markers.
List<string> str1 = GetList(s1);
List<string> str2 = GetList(s2);
while (str1.Count != str2.Count)
{
if (str1.Count < str2.Count)
{
str1.Add("");
}
else
{
str2.Add("");
}
}
int x1 = 0; int x2 = 0;
bool s1Status; bool s2Status;
//s1status ==false then string else int;
//s2status ==false then string else int;
int result = 0;
for (int i = 0; i < str1.Count && i < str2.Count; i++)
{
_ = int.TryParse(str1[i].ToString(), out int res);
if (res == 0)
{
s1Status = false;
}
else
{
x1 = Convert.ToInt32(str1[i].ToString());
s1Status = true;
}
_ = int.TryParse(str2[i].ToString(), out res);
if (res == 0)
{
s2Status = false;
}
else
{
x2 = Convert.ToInt32(str2[i].ToString());
s2Status = true;
}
//checking --the data comparision
if (!s2Status && !s1Status) //both are strings
{
result = str1[i].CompareTo(str2[i]);
}
else if (s2Status && s1Status) //both are intergers
{
if (x1 == x2)
{
if (str1[i].ToString().Length < str2[i].ToString().Length)
{
result = 1;
}
else if (str1[i].ToString().Length > str2[i].ToString().Length)
result = -1;
else
result = 0;
}
else
{
int st1ZeroCount = str1[i].ToString().Trim().Length - str1[i].ToString().TrimStart(new char[] { '0' }).Length;
int st2ZeroCount = str2[i].ToString().Trim().Length - str2[i].ToString().TrimStart(new char[] { '0' }).Length;
if (st1ZeroCount > st2ZeroCount)
result = -1;
else if (st1ZeroCount < st2ZeroCount)
result = 1;
else
result = x1.CompareTo(x2);
}
}
else
{
result = str1[i].CompareTo(str2[i]);
}
if (result == 0)
{
continue;
}
else
break;
}
return result;
}
#endregion
}
#endregion
}