UpdateGraphHistory ( PerWorkbookSettings oPerWorkbookSettings ) { Debug.Assert(oPerWorkbookSettings != null); AssertValid(); GraphHistory oGraphHistory = oPerWorkbookSettings.GraphHistory; if (!this.LayoutIsNull) { // Save the layout algorithm that was used to lay out the graph. oGraphHistory[GraphHistoryKeys.LayoutAlgorithm] = String.Format( "The graph was laid out using the {0} layout algorithm." , m_oLayoutManagerForContextMenu.LayoutText ); } // Save the graph's directedness. oGraphHistory[GraphHistoryKeys.GraphDirectedness] = String.Format( "The graph is {0}." , EnumUtil.SplitName( oNodeXLControl.Graph.Directedness.ToString(), EnumSplitStyle.AllWordsStartLowerCase) ); oPerWorkbookSettings.GraphHistory = oGraphHistory; }
UpdateAutoFillResultsLegend ( PerWorkbookSettings oPerWorkbookSettings ) { Debug.Assert(oPerWorkbookSettings != null); AssertValid(); // The autofill results are stored in the per-workbook settings. // Transfer them to the visual attributes legend control. AutoFillWorkbookResults oAutoFillWorkbookResults = oPerWorkbookSettings.AutoFillWorkbookResults; if (oAutoFillWorkbookResults.AutoFilledNonXYColumnCount > 0) { usrAutoFillResultsLegend.Update(oAutoFillWorkbookResults); } else { usrAutoFillResultsLegend.Clear(); } }
UpdateAxes ( PerWorkbookSettings oPerWorkbookSettings ) { Debug.Assert(oPerWorkbookSettings != null); AssertValid(); AutoFillWorkbookResults oAutoFillWorkbookResults = oPerWorkbookSettings.AutoFillWorkbookResults; String sXSourceColumnName, sYSourceColumnName; Double dXSourceCalculationNumber1, dXSourceCalculationNumber2, dXDestinationNumber1, dXDestinationNumber2, dYSourceCalculationNumber1, dYSourceCalculationNumber2, dYDestinationNumber1, dYDestinationNumber2; Boolean bXLogsUsed, bYLogsUsed; AutoFillNumericRangeColumnResults oVertexXResults = oAutoFillWorkbookResults.VertexXResults; AutoFillNumericRangeColumnResults oVertexYResults = oAutoFillWorkbookResults.VertexYResults; if (oVertexXResults.ColumnAutoFilled) { sXSourceColumnName = oVertexXResults.SourceColumnName; dXSourceCalculationNumber1 = oVertexXResults.SourceCalculationNumber1; dXSourceCalculationNumber2 = oVertexXResults.SourceCalculationNumber2; dXDestinationNumber1 = oVertexXResults.DestinationNumber1; dXDestinationNumber2 = oVertexXResults.DestinationNumber2; bXLogsUsed = oVertexXResults.LogsUsed; // The X and Y columns are always autofilled together. Debug.Assert(oVertexYResults.ColumnAutoFilled); sYSourceColumnName = oVertexYResults.SourceColumnName; dYSourceCalculationNumber1 = oVertexYResults.SourceCalculationNumber1; dYSourceCalculationNumber2 = oVertexYResults.SourceCalculationNumber2; dYDestinationNumber1 = oVertexYResults.DestinationNumber1; dYDestinationNumber2 = oVertexYResults.DestinationNumber2; bYLogsUsed = oVertexYResults.LogsUsed; } else { // The X and Y columns weren't autofilled. Use default axis // values. sXSourceColumnName = "X"; sYSourceColumnName = "Y"; dXSourceCalculationNumber1 = dXDestinationNumber1 = dYSourceCalculationNumber1 = dYDestinationNumber1 = VertexLocationConverter.MinimumXYWorkbook; dXSourceCalculationNumber2 = dXDestinationNumber2 = dYSourceCalculationNumber2 = dYDestinationNumber2 = VertexLocationConverter.MaximumXYWorkbook; bXLogsUsed = bYLogsUsed = false; } UpdateAxis(m_oNodeXLWithAxesControl.XAxis, sXSourceColumnName, dXSourceCalculationNumber1, dXSourceCalculationNumber2, dXDestinationNumber1, dXDestinationNumber2, bXLogsUsed); UpdateAxis(m_oNodeXLWithAxesControl.YAxis, sYSourceColumnName, dYSourceCalculationNumber1, dYSourceCalculationNumber2, dYDestinationNumber1, dYDestinationNumber2, bYLogsUsed); }
SummarizeGraph ( Microsoft.Office.Interop.Excel.Workbook workbook ) { Debug.Assert(workbook != null); PerWorkbookSettings oPerWorkbookSettings = new PerWorkbookSettings(workbook); OverallMetrics oOverallMetrics; ( new OverallMetricsReader() ).TryReadMetrics( workbook, out oOverallMetrics); String sTopNByMetrics; ( new TopNByMetricsReader() ).TryReadMetrics( workbook, out sTopNByMetrics); String sTwitterSearchNetworkTopItems; ( new TwitterSearchNetworkTopItemsReader() ).TryReadMetrics( workbook, out sTwitterSearchNetworkTopItems); return ( GraphSummarizer.SummarizeGraphInternal( oPerWorkbookSettings.GraphHistory, oPerWorkbookSettings.AutoFillWorkbookResults, oOverallMetrics, sTopNByMetrics, sTwitterSearchNetworkTopItems) ); }
AutomateOneWorkbookIndirect ( String nodeXLWorkbookFilePath, String workbookSettings ) { Debug.Assert( !String.IsNullOrEmpty(nodeXLWorkbookFilePath) ); Debug.Assert( !String.IsNullOrEmpty(workbookSettings) ); // Ideally, the Excel API would be used here to open the workbook // and run the AutomateOneWorkbook() method on it. Two things // make that impossible: // // 1. When you open a workbook using // Application.Workbooks.Open(), you get only a native Excel // workbook, not an "extended" ThisWorkbook object. // // Although a GetVstoObject() extension method is available to // convert a native Excel workbook to an extended workbook, // that method doesn't work on a native workbook opened via // the Excel API -- it always returns null. // // It might be possible to refactor AutomateOneWorkbook() to // require only a native workbook. However, problem 2 would // still make things impossible... // // 2. If this method is being run from a modal dialog, which it // is (see AutomateTasksDialog), then code in the workbook // that needs to be automated doesn't run until the modal // dialog closes. // // The following code works around these problems. Microsoft.Office.Interop.Excel.Application oExcelApplication = null; ExcelApplicationKiller oExcelApplicationKiller = null; try { // Use a new Application object for each workbook. If the same // Application object is reused, the memory used by each // workbook is never released and the machine will eventually // run out of memory. oExcelApplication = new Microsoft.Office.Interop.Excel.Application(); if (oExcelApplication == null) { throw new Exception("Excel couldn't be opened."); } // ExcelApplicationKiller requires that the application be // visible. oExcelApplication.Visible = true; oExcelApplicationKiller = new ExcelApplicationKiller( oExcelApplication); // Store an "automate tasks on open" flag in the workbook, // indicating that task automation should be run on it the next // time it's opened. This can be done via the Excel API. Microsoft.Office.Interop.Excel.Workbook oWorkbookToAutomate = ExcelUtil.OpenWorkbook(nodeXLWorkbookFilePath, oExcelApplication); PerWorkbookSettings oPerWorkbookSettings = new PerWorkbookSettings(oWorkbookToAutomate); oPerWorkbookSettings.WorkbookSettings = workbookSettings; oPerWorkbookSettings.AutomateTasksOnOpen = true; oWorkbookToAutomate.Save(); oWorkbookToAutomate.Close(false, Missing.Value, Missing.Value); oExcelApplication.Quit(); } catch (Exception oException) { ErrorUtil.OnException(oException); return; } finally { // Quitting the Excel application does not remove it from // memory. Kill its process. oExcelApplicationKiller.KillExcelApplication(); oExcelApplication = null; oExcelApplicationKiller = null; } try { // Now open the workbook in another instance of Excel, which // bypasses problem 2. Code in the workbook's Ribbon will // detect the flag's presence, run task automation on it, close // the workbook, and close the other instance of Excel. OpenWorkbookToAutomate(nodeXLWorkbookFilePath, 60 * 60); } catch (Exception oException) { ErrorUtil.OnException(oException); return; } }
AddCollapsedGroupAttributesInternal ( Microsoft.Office.Interop.Excel.Workbook oWorkbook, ReadWorkbookContext oReadWorkbookContext, ListObject oEdgeTable, ListObject oVertexTable, GroupInfo[] aoGroups ) { Debug.Assert(oWorkbook != null); Debug.Assert(oReadWorkbookContext != null); Debug.Assert(oEdgeTable != null); Debug.Assert(oVertexTable != null); Debug.Assert(aoGroups != null); Debug.Assert(aoGroups.Length > 0); // Check whether relevant columns have been autofilled using numerical // source columns. PerWorkbookSettings oPerWorkbookSettings = new PerWorkbookSettings(oWorkbook); AutoFillColorColumnResults oVertexColorResults = oPerWorkbookSettings.AutoFillWorkbookResults.VertexColorResults; Boolean bVertexColorColumnAutoFilled = oVertexColorResults.ColumnAutoFilled && !oVertexColorResults.ColumnAutoFilledWithCategories; AutoFillColorColumnResults oEdgeColorResults = oPerWorkbookSettings.AutoFillWorkbookResults.EdgeColorResults; Boolean bEdgeColorColumnAutoFilled = oEdgeColorResults.ColumnAutoFilled && !oEdgeColorResults.ColumnAutoFilledWithCategories; AutoFillNumericRangeColumnResults oEdgeWidthResults = oPerWorkbookSettings.AutoFillWorkbookResults.EdgeWidthResults; Boolean bEdgeWidthColumnAutoFilled = oEdgeWidthResults.ColumnAutoFilled; // Some user settings for autofill may be needed. // // Note: This is a design bug. The user's current settings should not // be required; everything needed here should come from the autofill // results. The long-term fix is to add a UseLogs property to the // AutoFillColorColumnResults class. AutoFillUserSettings oAutoFillUserSettings = new AutoFillUserSettings(); ColorColumnAutoFillUserSettings oVertexColorDetails = oAutoFillUserSettings.VertexColorDetails; ColorColumnAutoFillUserSettings oEdgeColorDetails = oAutoFillUserSettings.EdgeColorDetails; NumericRangeColumnAutoFillUserSettings oEdgeWidthDetails = oAutoFillUserSettings.EdgeWidthDetails; // The key is the row ID for each visible row in the vertex table and // the value is value of the source column cell in that row that was // used to autofill the vertex color column, if it was autofilled. Dictionary<Int32, Object> oVertexColorSourceDictionary = bVertexColorColumnAutoFilled ? GetRowIDDictionary(oVertexTable, oVertexColorResults.SourceColumnName) : null; // Ditto for edge colors and edge widths. Dictionary<Int32, Object> oEdgeColorSourceDictionary = bEdgeColorColumnAutoFilled ? GetRowIDDictionary(oEdgeTable, oEdgeColorResults.SourceColumnName) : null; Dictionary<Int32, Object> oEdgeWidthSourceDictionary = bEdgeWidthColumnAutoFilled ? GetRowIDDictionary(oEdgeTable, oEdgeWidthResults.SourceColumnName) : null; // Only motifs need to have attributes added to them. foreach ( ExcelTemplateGroupInfo oGroup in aoGroups.Where( oGroup => oGroup.CollapsedAttributes != null) ) { CollapsedGroupAttributes oCollapsedGroupAttributes = CollapsedGroupAttributes.FromString( oGroup.CollapsedAttributes); String sType = oCollapsedGroupAttributes.GetGroupType(); if ( sType == CollapsedGroupAttributeValues.FanMotifType || sType == CollapsedGroupAttributeValues.DConnectorMotifType || sType == CollapsedGroupAttributeValues.CliqueMotifType ) { AddVertexColorAttributeToMotif(oGroup, sType, bVertexColorColumnAutoFilled, oVertexColorResults, oVertexColorDetails, oVertexColorSourceDictionary, oReadWorkbookContext, oCollapsedGroupAttributes); } if (sType == CollapsedGroupAttributeValues.DConnectorMotifType) { Int32 iAnchorVertices; if ( oCollapsedGroupAttributes.TryGetValue( CollapsedGroupAttributeKeys.AnchorVertices, out iAnchorVertices) ) { AddEdgeColorAttributesToDConnectorMotif(oGroup, bEdgeColorColumnAutoFilled, oEdgeColorResults, oEdgeColorDetails, oEdgeColorSourceDictionary, oReadWorkbookContext, oCollapsedGroupAttributes, iAnchorVertices); AddEdgeWidthAttributesToDConnectorMotif(oGroup, bEdgeWidthColumnAutoFilled, oEdgeWidthResults, oEdgeWidthDetails, oEdgeWidthSourceDictionary, oReadWorkbookContext, oCollapsedGroupAttributes, iAnchorVertices); } } oGroup.CollapsedAttributes = oCollapsedGroupAttributes.ToString(); } }
UpdateGraphHistoryAfterImportWithoutPermissionCheck ( Microsoft.Office.Interop.Excel.Workbook destinationNodeXLWorkbook, String importDescription, String suggestedFileNameNoExtension, PerWorkbookSettings perWorkbookSettings ) { Debug.Assert(destinationNodeXLWorkbook != null); Debug.Assert(perWorkbookSettings != null); perWorkbookSettings.SetGraphHistoryValue( GraphHistoryKeys.ImportDescription, importDescription ?? String.Empty); perWorkbookSettings.SetGraphHistoryValue( GraphHistoryKeys.ImportSuggestedFileNameNoExtension, suggestedFileNameNoExtension ?? String.Empty); }
ReadWorkbookInternal ( Microsoft.Office.Interop.Excel.Workbook workbook, ReadWorkbookContext readWorkbookContext ) { Debug.Assert(readWorkbookContext != null); Debug.Assert(workbook != null); AssertValid(); if (readWorkbookContext.PopulateVertexWorksheet) { // Create and use the object that fills in the vertex worksheet. VertexWorksheetPopulator oVertexWorksheetPopulator = new VertexWorksheetPopulator(); try { oVertexWorksheetPopulator.PopulateVertexWorksheet( workbook, false); } catch (WorkbookFormatException) { // Ignore this type of error, which occurs when the vertex // worksheet is missing, for example. } } // Create a graph with the appropriate directedness. PerWorkbookSettings oPerWorkbookSettings = new PerWorkbookSettings(workbook); IGraph oGraph = new Graph(oPerWorkbookSettings.GraphDirectedness); // Read the edge worksheet. This adds data to oGraph, // ReadWorkbookContext.VertexNameDictionary, and // ReadWorkbookContext.EdgeIDDictionary. EdgeWorksheetReader oEdgeWorksheetReader = new EdgeWorksheetReader(); oEdgeWorksheetReader.ReadWorksheet(workbook, readWorkbookContext, oGraph); oEdgeWorksheetReader = null; // Read the vertex worksheet. This adds metadata to the vertices in // oGraph; adds any isolated vertices to oGraph and // ReadWorkbookContext.VertexNameDictionary; and removes any skipped // vertices (and their incident edges) from // ReadWorkbookContext.VertexNameDictionary, // ReadWorkbookContext.EdgeIDDictionary, and oGraph. VertexWorksheetReader oVertexWorksheetReader = new VertexWorksheetReader(); oVertexWorksheetReader.ReadWorksheet(workbook, readWorkbookContext, oGraph); oVertexWorksheetReader = null; if (readWorkbookContext.ReadGroups) { // Read the group worksheets. This adds metadata to the vertices // in oGraph and to oGraph itself. GroupWorksheetReader oGroupWorksheetReader = new GroupWorksheetReader(); oGroupWorksheetReader.ReadWorksheet(workbook, readWorkbookContext, oGraph); oGroupWorksheetReader = null; // Add to the graph any collapsed group attributes that can only be // added after the workbook is read. CollapsedGroupAttributeAdder.AddCollapsedGroupAttributes( workbook, readWorkbookContext, oGraph); } return (oGraph); }