public void CleanupFlowThroughColumns() { for (int rhIndex = 0; rhIndex < currentFilingSummary.MyReports.Count; rhIndex++) { ReportHeader rh = currentFilingSummary.MyReports[rhIndex] as ReportHeader; //Equity reports that do not have segments still need to have flow through columns //cleaned up because they were not processed with the regular equity processing logic bool isEquityStatement = false; if (ReportUtils.IsStatementOfEquityCombined(rh.LongName)) { isEquityStatement = true; } if (isEquityStatement) { string instanceFile = Path.Combine(this.currentReportDirectory, rh.XmlFileName); InstanceReport ir = InstanceReport.LoadXml(instanceFile); if (ir.IsEquityReport) { continue; } } if (rh.ReportType == ReportHeaderType.Sheet || rh.ReportType == ReportHeaderType.Notes) { if (cleanupStatementsOnly) { if (ReportUtils.IsStatement(rh.LongName) == true) { this.currentFilingSummary.TraceInformation("Process Flow-Through: " + rh.LongName); InstanceReport.ElementSegmentCombinations allInUseElementsSegments = this.BuildInUseElementSegmentCombinationsForAllReports(rh); this.CleanupColumns(rh, allInUseElementsSegments); this.uniqueReportElementSegmentCombos.Remove(rh.XmlFileName); } } else { this.currentFilingSummary.TraceInformation("Process Flow-Through: " + rh.LongName); InstanceReport.ElementSegmentCombinations allInUseElementsSegments = this.BuildInUseElementSegmentCombinationsForAllReports(rh); this.CleanupColumns(rh, allInUseElementsSegments); this.uniqueReportElementSegmentCombos.Remove(rh.XmlFileName); } } } this.uniqueReportElements = new Dictionary <string, List <string> >(); this.uniqueReportSegments = new Dictionary <string, List <string> >(); this.uniqueReportElementSegmentCombos = new Dictionary <string, InstanceReport.ElementSegmentCombinations>(); }
/// <summary> /// Builds a nested dictionary of all elements and which Segments they are combined with for all reports. /// </summary> /// <param name="rhCurrent">The current <see cref="ReportHeader"/> - its report will be skipped from cataloging.</param> /// <returns></returns> private InstanceReport.ElementSegmentCombinations BuildInUseElementSegmentCombinationsForAllReports(ReportHeader rhCurrent) { InstanceReport.ElementSegmentCombinations allReportCombinations = new InstanceReport.ElementSegmentCombinations(); foreach (ReportHeader rh in this.currentFilingSummary.MyReports) { if (rh.XmlFileName == rhCurrent.XmlFileName) { continue; } InstanceReport.ElementSegmentCombinations reportCombinations = this.BuildInUseElementSegmentCombinationsForCurrentReport(rh); if (reportCombinations != null) { allReportCombinations.Merge(reportCombinations); } } return(allReportCombinations); }
/// <summary> /// Builds a nested dictionary of all elements and which Segments they are combined with for 1 report, specified by <paramref name="rh"/>. /// </summary> /// <param name="rh">The <see cref="ReportHeader"/> whose element/segment combinations should be loaded.</param> /// <returns></returns> private InstanceReport.ElementSegmentCombinations BuildInUseElementSegmentCombinationsForCurrentReport(ReportHeader rh) { if (rh.ReportType == ReportHeaderType.Sheet || rh.ReportType == ReportHeaderType.Notes) { if (!this.uniqueReportElementSegmentCombos.ContainsKey(rh.XmlFileName) || this.uniqueReportElementSegmentCombos == null || this.uniqueReportElementSegmentCombos.Count == 0) { InstanceReport report = InstanceReport.LoadXml(Path.Combine(this.currentReportDirectory, rh.XmlFileName)); InstanceReport.ElementSegmentCombinations elementSegmentCombinations = report.GetUniqueInUseElementSegmentCombinations(); this.uniqueReportElementSegmentCombos[rh.XmlFileName] = elementSegmentCombinations; } } if (this.uniqueReportElementSegmentCombos.ContainsKey(rh.XmlFileName)) { return(uniqueReportElementSegmentCombos[rh.XmlFileName]); } return(null); }
/// <summary> /// Go thorugh each column to determine if the columns should be removed -- /// if all elements (that have data) in the columns can be found in other reports then consider this a flow thru column and delete it. /// For "disclosures", if one element or one dimension member s unique, do remove ANY columns from the disclosure /// </summary> /// <param name="rh"></param> /// <param name="allInUseElementsSegments"></param> private void CleanupColumns(ReportHeader rh, InstanceReport.ElementSegmentCombinations allInUseElementsSegments) { string filePath = Path.Combine(this.currentReportDirectory, rh.XmlFileName); InstanceReport report = InstanceReport.LoadXml(filePath); if (report == null) { return; } InstanceReportColumn lastSegmentColumn = null; bool hasSegmentsOnRows = report.HasSegmentsOnRows(); List <InstanceReportColumn> columnsToRetain = new List <InstanceReportColumn>(); foreach (InstanceReportRow row in report.Rows) { if (hasSegmentsOnRows) { if (row.OriginalInstanceReportColumn != null) { lastSegmentColumn = row.OriginalInstanceReportColumn; } } //we can't test this row if (string.IsNullOrEmpty(row.ElementName)) { continue; } //we can't test this row if (row.IsEmpty()) { continue; } for (int c = 0; c < row.Cells.Count; c++) { //skip this cell if we already have this column InstanceReportColumn currentColumn = report.Columns[c]; if (columnsToRetain.Contains(currentColumn)) { continue; } //we only want columns for cells which have data Cell cell = row.Cells[c]; if (!cell.HasData) { continue; } //if the element doesn't even exist, we're set - add the column InstanceReportColumn segmentColumn = hasSegmentsOnRows ? lastSegmentColumn : currentColumn; if (!allInUseElementsSegments.ContainsElement(row.ElementName)) { columnsToRetain.Add(currentColumn); } else if (segmentColumn != null) { if (segmentColumn.Segments != null && segmentColumn.Segments.Count > 0) { //if the element exists, but maybe its combination with the segments does not StringBuilder sb = new StringBuilder(); foreach (string segmentKey in segmentColumn.GetUniqueInUseSegments().Keys) { sb.AppendLine(segmentKey); } if (!allInUseElementsSegments.ContainsElementAndSegments(row.ElementName, sb.ToString())) { columnsToRetain.Add(currentColumn); } } } } if (columnsToRetain.Count == report.Columns.Count) { return; } } if (columnsToRetain.Count == 0 || columnsToRetain.Count == report.Columns.Count) { return; } List <InstanceReportColumn> columnsToRemove = report.Columns.FindAll(col => !columnsToRetain.Contains(col)); foreach (InstanceReportColumn col in columnsToRemove) { this.currentFilingSummary.TraceInformation("\tProcess Flow-Through: Removing column '" + col.Label + "'"); col.RemoveSelf(report); } if (report.Columns.Count > 1) { report.PromoteSharedColumnLabelsAfterRemoveFlowThroughColumns(); } report.BuildXMLDocument(filePath, false, false, this.currentFilingSummary); }
/// <summary> /// For each report, check to see if at least ONE element do not exist in all other reports. If not, delete the report. /// For each column, check to see if at least ONE element do not exist in all other reports. If not, delete the column. /// </summary> public void CleanupFlowThroughReports() { ArrayList reportsToRemove = new ArrayList(); foreach (ReportHeader rh in this.currentFilingSummary.MyReports) { //EH: Based on Christy's request, if the report is Stockholder's Equity, do not remove columns //DuPont and Oceanic filings will not look correct if we remove the columns. All elements for certain periods are in both //Balance Sheet and Stockholder's Equity if ((rh.ReportType == ReportHeaderType.Sheet || rh.ReportType == ReportHeaderType.Notes)) { if (!rh.IsStatementOfStockholdersEquity()) { Dictionary <string, int> htElementsCurrentReport = this.BuildInUseElementsForCurrentReport(rh); Dictionary <string, int> htElementsOtherReports = this.BuildInUseElementsForAllReports(rh); //Dictionary<string, int> uniqueSegments = this.BuildInUseSegmentsForAllReports( rh ); int elementFoundInOtherReports = 0; foreach (string currentElementName in htElementsCurrentReport.Keys) { if (htElementsOtherReports.ContainsKey(currentElementName)) { elementFoundInOtherReports += 1; } } if (elementFoundInOtherReports == htElementsCurrentReport.Count) //all elements in other report { //Remove the report if (!ReportUtils.IsHighlights(rh.ShortName) && !ReportUtils.IsBalanceSheet(rh.ShortName) && !ReportUtils.IsIncomeStatement(rh.ShortName)) { reportsToRemove.Add(rh); } } else { InstanceReport.ElementSegmentCombinations allInUseElementsSegments = this.BuildInUseElementSegmentCombinationsForAllReports(rh); this.CleanupColumns(rh, allInUseElementsSegments); this.uniqueReportElementSegmentCombos.Remove(rh.XmlFileName); //CleanupColumns( rh, htElementsOtherReports, uniqueSegments ); } } } } if (reportsToRemove.Count > 0) { foreach (ReportHeader rhToRemove in reportsToRemove) { //delete from MyFilingSummary for (int rIndex = currentFilingSummary.MyReports.Count - 1; rIndex >= 0; rIndex--) { ReportHeader rh1 = currentFilingSummary.MyReports[rIndex] as ReportHeader; if (rh1.XmlFileName == rhToRemove.XmlFileName) { currentFilingSummary.MyReports.RemoveAt(rIndex); break; } } string fileName = currentReportDirectory + Path.DirectorySeparatorChar + rhToRemove.XmlFileName; this.currentFilingSummary.TraceWarning("Process Flow-Through Report: removing '" + rhToRemove.LongName + "'"); File.Delete(fileName); } } }