CreateAndSaveSubgraphImages ( IGraph oSubgraph, String sVertexName, CreateSubgraphImagesAsyncArgs oCreateSubgraphImagesAsyncArgs, TemporaryImages oThumbnailImages ) { Debug.Assert(oSubgraph != null); Debug.Assert(!String.IsNullOrEmpty(sVertexName)); Debug.Assert(oCreateSubgraphImagesAsyncArgs != null); Debug.Assert(oThumbnailImages != null); AssertValid(); if (oCreateSubgraphImagesAsyncArgs.SaveToFolder) { CreateAndSaveSubgraphImageInFolder(oSubgraph, sVertexName, oCreateSubgraphImagesAsyncArgs); } if (oCreateSubgraphImagesAsyncArgs.CreateThumbnails) { CreateAndSaveThumbnailImage(oSubgraph, sVertexName, oCreateSubgraphImagesAsyncArgs, oThumbnailImages); } }
CreateAndSaveThumbnailImage ( IGraph oSubgraph, String sVertexName, CreateSubgraphImagesAsyncArgs oCreateSubgraphImagesAsyncArgs, TemporaryImages oThumbnailImages ) { Debug.Assert(oSubgraph != null); Debug.Assert(!String.IsNullOrEmpty(sVertexName)); Debug.Assert(oCreateSubgraphImagesAsyncArgs != null); Debug.Assert(oCreateSubgraphImagesAsyncArgs.CreateThumbnails); Debug.Assert(oThumbnailImages != null); AssertValid(); if (oThumbnailImages.Folder == null) { // Create a temporary folder where the thumbnail images will be // stored. String sTemporaryFolder = Path.Combine( Path.GetTempPath(), Path.GetRandomFileName() ); Directory.CreateDirectory(sTemporaryFolder); oThumbnailImages.Folder = sTemporaryFolder; } // Save the graph to a bitmap. Bitmap oBitmap = CreateSubgraphImage(oSubgraph, oCreateSubgraphImagesAsyncArgs, oCreateSubgraphImagesAsyncArgs.ThumbnailSizePx); try { // Save the bitmap in the temporary folder. String sTemporaryFileName = SaveSubgraphImage(oBitmap, oThumbnailImages.Folder, sVertexName, oCreateSubgraphImagesAsyncArgs ); // Add the file name to the dictionary. They key is the vertex // name and the value is the file name, without a path. oThumbnailImages.FileNames[sVertexName] = sTemporaryFileName; } finally { GraphicsUtil.DisposeBitmap(ref oBitmap); } }
CreateSubgraphImagesInternal ( CreateSubgraphImagesAsyncArgs oCreateSubgraphImagesAsyncArgs, BackgroundWorker oBackgroundWorker, DoWorkEventArgs oDoWorkEventArgs ) { Debug.Assert(oCreateSubgraphImagesAsyncArgs != null); Debug.Assert(oBackgroundWorker != null); Debug.Assert(oDoWorkEventArgs != null); AssertValid(); // Create an object to keep track of the thumbnail images this method // creates and stores in a temporary folder. TemporaryImages oThumbnailImages = new TemporaryImages(); oThumbnailImages.ImageSizePx = oCreateSubgraphImagesAsyncArgs.ThumbnailSizePx; oDoWorkEventArgs.Result = oThumbnailImages; ICollection <IVertex> oVertices; if (oCreateSubgraphImagesAsyncArgs.SelectedVerticesOnly) { oVertices = oCreateSubgraphImagesAsyncArgs.SelectedVertices; } else { oVertices = oCreateSubgraphImagesAsyncArgs.Graph.Vertices; } Int32 iSubgraphsCreated = 0; Boolean bSaveToFolder = oCreateSubgraphImagesAsyncArgs.SaveToFolder; Boolean bCreateThumbnails = oCreateSubgraphImagesAsyncArgs.CreateThumbnails; if (bSaveToFolder || bCreateThumbnails) { foreach (IVertex oVertex in oVertices) { if (oBackgroundWorker.CancellationPending) { if (oThumbnailImages.Folder != null) { // Delete the entire temporary folder. Directory.Delete(oThumbnailImages.Folder, true); oThumbnailImages.Folder = null; } oDoWorkEventArgs.Cancel = true; break; } String sVertexName = oVertex.Name; oBackgroundWorker.ReportProgress(0, String.Format( "Creating subgraph image for \"{0}\"." , sVertexName )); // Create a subgraph for the vertex. IGraph oSubgraph = CreateSubgraph(oVertex, oCreateSubgraphImagesAsyncArgs); // Create and save images for the subgraph. CreateAndSaveSubgraphImages(oSubgraph, sVertexName, oCreateSubgraphImagesAsyncArgs, oThumbnailImages); iSubgraphsCreated++; } } oBackgroundWorker.ReportProgress(0, String.Format( "Done. Created {0} subgraph {1}." , iSubgraphsCreated.ToString(ExcelTemplateForm.Int32Format), StringUtil.MakePlural("image", iSubgraphsCreated) )); }
PopulateColumnWithImages ( Workbook workbook, String worksheetName, String tableName, String imageColumnName, String keyColumnName, TemporaryImages temporaryImages ) { Debug.Assert(workbook != null); Debug.Assert(!String.IsNullOrEmpty(worksheetName)); Debug.Assert(!String.IsNullOrEmpty(tableName)); Debug.Assert(!String.IsNullOrEmpty(imageColumnName)); Debug.Assert(!String.IsNullOrEmpty(keyColumnName)); Debug.Assert(temporaryImages != null); ListObject oTable; Range oKeyColumnData; // Get the table and the key column data. if (!ExcelUtil.TryGetTable(workbook, worksheetName, tableName, out oTable) || !ExcelUtil.TryGetTableColumnData(oTable, keyColumnName, out oKeyColumnData) ) { // Nothing can be done without the table or key column. return; } Range oImageColumnData; // Add the image column if it doesn't already exist. if (!TryGetImageColumnData(oTable, imageColumnName, out oImageColumnData)) { // The image column doesn't exist and couldn't be added. return; } String sFolder = temporaryImages.Folder; if (sFolder == null) { // No temporary images were created, so nothing more needs to be // done. return; } // Reduce the key and image column data to visible areas only. Range oVisibleKeyColumnData, oVisibleImageColumnData; if ( !ExcelUtil.TryGetVisibleRange(oKeyColumnData, out oVisibleKeyColumnData) || !ExcelUtil.TryGetVisibleRange(oImageColumnData, out oVisibleImageColumnData) ) { return; } Int32 iAreas = oVisibleKeyColumnData.Areas.Count; if (iAreas != oVisibleImageColumnData.Areas.Count) { return; } // Get the size of each image, in points. SizeF oImageSizePt = GetImageSizePt(temporaryImages.ImageSizePx, workbook); // Get any old images in the image column as a dictionary. This // significantly speeds up the deletion of the old images, because // Excel doesn't have to do a linear search on Shape.Name as each image // is deleted by PopulateAreaWithImages(). Debug.Assert(oTable.Parent is Worksheet); Dictionary <String, Microsoft.Office.Interop.Excel.Shape> oOldImagesInColumn = GetImagesInColumn((Worksheet)oTable.Parent, imageColumnName); // Populate each area of the image column with images. workbook.Application.ScreenUpdating = false; try { for (Int32 iArea = 1; iArea <= iAreas; iArea++) { PopulateAreaWithImages(oVisibleKeyColumnData.Areas[iArea], oVisibleImageColumnData.Areas[iArea], imageColumnName, oImageSizePt, oOldImagesInColumn, temporaryImages); } } finally { workbook.Application.ScreenUpdating = true; } // Delete the entire temporary folder. try { Directory.Delete(sFolder, true); } catch (IOException) { // A user reported the following exception thrown from the above // Directory.Delete() call: // // "System.IO.IOException: The directory is not empty.: // // Others have reported this happenning at random times. For // example: // // http://forums.asp.net/p/1114215/1722498.aspx // // I have also seen it happen from the command line outside of // .NET. When it occurs, the directory IS empty but cannot be // accessed in any way. The directory disappears when the machine // is rebooted. // // I can't figure out the cause or the fix. Ignore the problem, // which seems to be benign. } }
PopulateAreaWithImages ( Range oKeyColumnArea, Range oImageColumnArea, String sImageColumnName, SizeF oImageSizePt, Dictionary <String, Microsoft.Office.Interop.Excel.Shape> oOldImagesInColumn, TemporaryImages oTemporaryImages ) { Debug.Assert(oKeyColumnArea != null); Debug.Assert(oImageColumnArea != null); Debug.Assert(!String.IsNullOrEmpty(sImageColumnName)); Debug.Assert(oOldImagesInColumn != null); Debug.Assert(oTemporaryImages != null); // Gather some required information. Int32 iRows = oKeyColumnArea.Rows.Count; Debug.Assert(iRows == oImageColumnArea.Rows.Count); Debug.Assert(oKeyColumnArea.Parent is Worksheet); Worksheet oWorksheet = (Worksheet)oKeyColumnArea.Parent; Microsoft.Office.Interop.Excel.Shapes oShapes = oWorksheet.Shapes; Object [,] aoKeyValues = ExcelUtil.GetRangeValues(oKeyColumnArea); Dictionary <String, String> oFileNames = oTemporaryImages.FileNames; // Set the row heights to fit the images. oKeyColumnArea.RowHeight = oImageSizePt.Height + 2 * ImageMarginPt; // Get the first cell in the image column. Range oImageCell = (Range)oImageColumnArea.Cells[1, 1]; // Loop through the area's rows. for (Int32 iRow = 1; iRow <= iRows; iRow++) { String sKey, sFileName; // Check whether the row's key cell has a corresponding file name // in the dictionary. if ( ExcelUtil.TryGetNonEmptyStringFromCell(aoKeyValues, iRow, 1, out sKey) && oFileNames.TryGetValue(sKey, out sFileName) ) { // Give the picture a name that can be recognized by // GetImagesInColumn(). String sPictureName = sImageColumnName + "-" + sKey; Microsoft.Office.Interop.Excel.Shape oPicture; // If an old version of the picture remains from a previous // call to this method, delete it. if (oOldImagesInColumn.TryGetValue(sPictureName, out oPicture)) { oPicture.Delete(); } String sFileNameWithPath = Path.Combine( oTemporaryImages.Folder, sFileName); oPicture = oShapes.AddPicture(sFileNameWithPath, MsoTriState.msoFalse, MsoTriState.msoCTrue, (Single)(Double)oImageCell.Left + ImageMarginPt, (Single)(Double)oImageCell.Top + ImageMarginPt, oImageSizePt.Width, oImageSizePt.Height ); oPicture.Name = sPictureName; } // Move down one cell in the image column. oImageCell = oImageCell.get_Offset(1, 0); } }
OnImageCreationCompleted ( RunWorkerCompletedEventArgs e ) { AssertValid(); if (e.Cancelled) { this.State = DialogState.Idle; lblStatus.Text = "Image creation stopped."; } else if (e.Error != null) { this.State = DialogState.Idle; Exception oException = e.Error; if (oException is System.IO.IOException) { lblStatus.Text = "Image creation error."; this.ShowWarning(oException.Message); } else { ErrorUtil.OnException(oException); } } else { // Success. Were temporary images created that need to be inserted // into the vertex worksheet? Debug.Assert(e.Result is TemporaryImages); TemporaryImages oTemporaryImages = (TemporaryImages)e.Result; if (oTemporaryImages.Folder != null) { // Yes. Insert them, then delete the temporary images. this.State = DialogState.PopulatingImageColumn; String sLastStatusFromSubgraphImageCreator = lblStatus.Text; lblStatus.Text = "Inserting subgraph thumbnails into the worksheet. Please" + " wait..."; TableImagePopulator.PopulateColumnWithImages(m_oWorkbook, WorksheetNames.Vertices, TableNames.Vertices, VertexTableColumnNames.SubgraphImage, VertexTableColumnNames.VertexName, oTemporaryImages ); lblStatus.Text = sLastStatusFromSubgraphImageCreator; } this.State = DialogState.Idle; if (m_eMode == DialogMode.Automate) { this.Close(); } } }