sysperfana/heapanalyser/Libraries/Engine/HeapComparisonLib/Data/ComparsionWriter.cs
changeset 8 15296fd0af4a
equal deleted inserted replaced
7:8e12a575a9b5 8:15296fd0af4a
       
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 *
       
     5 * Redistribution and use in source and binary forms, with or without
       
     6 * modification, are permitted provided that the following conditions are met:
       
     7 *
       
     8 * - Redistributions of source code must retain the above copyright notice,
       
     9 *   this list of conditions and the following disclaimer.
       
    10 * - Redistributions in binary form must reproduce the above copyright notice,
       
    11 *   this list of conditions and the following disclaimer in the documentation
       
    12 *   and/or other materials provided with the distribution.
       
    13 * - Neither the name of Nokia Corporation nor the names of its contributors
       
    14 *   may be used to endorse or promote products derived from this software
       
    15 *   without specific prior written permission.
       
    16 *
       
    17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
       
    18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
       
    20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
       
    21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
       
    22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
       
    23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
       
    24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
       
    25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
       
    26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
       
    27 * POSSIBILITY OF SUCH DAMAGE.
       
    28 * 
       
    29 * Initial Contributors:
       
    30 * Nokia Corporation - initial contribution.
       
    31 *
       
    32 * Contributors:
       
    33 *
       
    34 * Description: 
       
    35 *
       
    36 */
       
    37 
       
    38 using System;
       
    39 using System.Text;
       
    40 using System.Text.RegularExpressions;
       
    41 using System.Threading;
       
    42 using System.Globalization;
       
    43 using System.Collections;
       
    44 using System.Collections.Generic;
       
    45 using SymbianUtils;
       
    46 using SymbianUtils.Range;
       
    47 using SymbianUtils.RawItems;
       
    48 using SymbianUtils.TextUtilities.Readers.Types.Array;
       
    49 using HeapLib.Cells;
       
    50 using HeapLib.Array;
       
    51 using HeapLib.Statistics;
       
    52 using System.Runtime.InteropServices;
       
    53 using Microsoft.Office.Interop.Excel;
       
    54 using Excel = Microsoft.Office.Interop.Excel;
       
    55 using HeapComparisonLib.Data.Pages;
       
    56 using SymbianExcelUtils;
       
    57 using HeapLib.Statistics.Types;
       
    58 using HeapLib.Statistics.Tracking.BySymbol;
       
    59 using HeapLib.Statistics.Tracking.Base;
       
    60 
       
    61 namespace HeapComparisonLib.Data
       
    62 {
       
    63     public class ComparisonWriter : AsyncTextWriterBase
       
    64     {
       
    65         #region Constructors
       
    66         public ComparisonWriter( ComparsionEngine aEngine, string aFileName )
       
    67         {
       
    68             iEngine = aEngine;
       
    69             iFileName = aFileName;
       
    70         }
       
    71         #endregion
       
    72 
       
    73         #region API
       
    74         public void SaveAsExcel()
       
    75         {
       
    76             AsyncWrite();
       
    77         }
       
    78         #endregion
       
    79 
       
    80         #region Properties
       
    81         #endregion
       
    82 
       
    83         #region From AsyncWriterBase
       
    84         protected override void HandleWriteStarted()
       
    85         {
       
    86             // There are problems with exporting to excel on non-English machines
       
    87             // See: http://www.made4dotnet.com/Default.aspx?tabid=141&aid=15
       
    88             iOriginalCulture = System.Threading.Thread.CurrentThread.CurrentCulture;
       
    89             ChangeToEnglishCulture();
       
    90 
       
    91             iExcelApp = new Microsoft.Office.Interop.Excel.Application();
       
    92             iExcelApp.DisplayAlerts = false;
       
    93 
       
    94             Workbooks workbooks = iExcelApp.Workbooks;
       
    95             workbooks.Add( XlWBATemplate.xlWBATWorksheet );
       
    96             iWorkbook = workbooks.get_Item( workbooks.Count );
       
    97 
       
    98             // Create summary sheet
       
    99             Sheets sheets = iWorkbook.Worksheets;
       
   100             iSummary = (Worksheet) sheets.get_Item( 1 );
       
   101             CreateSummary( iSummary );
       
   102 
       
   103             // Create pages
       
   104             iPages.Add( new Pages.PageUnchanged( iEngine.ResultsUnchanged, iWorkbook ) );
       
   105             iPages.Add( new Pages.PageUnique( iEngine.Reconstructor2, iEngine.ResultsUniqueInHeap2, iWorkbook, "Unique in Heap 2", 2, 1 ) );
       
   106             iPages.Add( new Pages.PageUnique( iEngine.Reconstructor1, iEngine.ResultsUniqueInHeap1, iWorkbook, "Unique in Heap 1", 1, 2 ) );
       
   107             iPages.Add( new Pages.PageSimpleListing( iEngine.ResultsUnchangedLengthButDifferentContents, iWorkbook, "Same length, different contents" ) );
       
   108             iPages.Add( new Pages.PageSimpleListing( iEngine.ResultsChanged, iWorkbook, "Changed", false ) );
       
   109         }
       
   110 
       
   111         protected override void HandleWriteCompleted()
       
   112         {
       
   113             try
       
   114             {
       
   115                 base.HandleWriteCompleted();
       
   116 
       
   117                 // Populate summary sheet
       
   118                 FinaliseSummary( iSummary );
       
   119 
       
   120                 // Activate summary
       
   121                 ( (Microsoft.Office.Interop.Excel._Worksheet) iSummary ).Activate();
       
   122 
       
   123                 // Save and close workbook
       
   124                 SaveFile();
       
   125 
       
   126                 // Exit Excel
       
   127                 SymbianExcelUtils.Utils.CloseExcel( iExcelApp );
       
   128             }
       
   129             catch
       
   130             {
       
   131             }
       
   132             finally
       
   133             {
       
   134                 RestoreOriginalCulture();
       
   135             }
       
   136         }
       
   137 
       
   138         public override void ExportData()
       
   139         {
       
   140             PageBase page = null;
       
   141             //
       
   142             lock ( this )
       
   143             {
       
   144                 if ( iCurrentPageIndex < iPages.Count )
       
   145                 {
       
   146                     page = iPages[ iCurrentPageIndex++ ];
       
   147                 }
       
   148             }
       
   149             //
       
   150             if ( page != null )
       
   151             {
       
   152                 page.SaveToPage();
       
   153             }
       
   154         }
       
   155 
       
   156         public override long Size
       
   157         {
       
   158             get
       
   159             {
       
   160                 long size = 0;
       
   161                 lock ( iPages )
       
   162                 {
       
   163                     size = iPages.Count;
       
   164                 }
       
   165                 return size;
       
   166             }
       
   167         }
       
   168 
       
   169         public override long Position
       
   170         {
       
   171             get
       
   172             {
       
   173                 long pos = 0;
       
   174                 lock ( this )
       
   175                 {
       
   176                     pos = iCurrentPageIndex;
       
   177                 }
       
   178                 return pos;
       
   179             }
       
   180         }
       
   181         #endregion
       
   182 
       
   183         #region Internal methods
       
   184         private void SaveFile()
       
   185         {
       
   186             // Delete any existing file with the same name
       
   187             System.IO.FileInfo fileInfo = new System.IO.FileInfo( iFileName );
       
   188             if ( fileInfo.Exists )
       
   189             {
       
   190                 fileInfo.Delete();
       
   191             }
       
   192 
       
   193             // Save and tidy up
       
   194             try
       
   195             {
       
   196                 iWorkbook.SaveAs( iFileName,
       
   197 								  XlFileFormat.xlWorkbookNormal,
       
   198 								  Type.Missing,
       
   199 								  Type.Missing,
       
   200 								  Type.Missing,
       
   201 								  Type.Missing,
       
   202 								  XlSaveAsAccessMode.xlNoChange,
       
   203 								  Type.Missing,
       
   204 								  Type.Missing,
       
   205 								  Type.Missing,
       
   206 								  Type.Missing,
       
   207 								  Type.Missing );
       
   208             }
       
   209             catch ( System.IO.IOException )
       
   210             {
       
   211             }
       
   212 
       
   213             iWorkbook.Close( false, Type.Missing, Type.Missing );
       
   214         }
       
   215 
       
   216         private void CreateSummary( Worksheet aSheet )
       
   217         {
       
   218             aSheet.Name = "Summary";
       
   219             //
       
   220             int row = 0;
       
   221             //
       
   222             row++;
       
   223             Utils.SetValue( row, 2, aSheet, "Heap 1" ).AddComment( "From: " + iEngine.Reconstructor1.SourceData.FileName );
       
   224             Utils.SetValue( row, 3, aSheet, "Heap 2" ).AddComment( "From: " + iEngine.Reconstructor2.SourceData.FileName );
       
   225             Utils.SetValue( row, 4, aSheet, "Delta" );
       
   226             Utils.MakeBoxedTitleRow( 1, 4, aSheet, 0xFF0000 );
       
   227         }
       
   228 
       
   229         private void FinaliseSummary( Worksheet aSheet )
       
   230         {
       
   231             int row = 1;
       
   232 
       
   233             {
       
   234                 long heapSize1 = iEngine.Reconstructor1.Statistics.HeapSize;
       
   235                 long heapSize2 = iEngine.Reconstructor2.Statistics.HeapSize;
       
   236                 row++;
       
   237                 Utils.SetValue( row, 1, aSheet, "Heap Chunk Size" );
       
   238                 Utils.SetValue( row, 2, aSheet, heapSize1.ToString() );
       
   239                 Utils.SetValue( row, 3, aSheet, heapSize2.ToString() );
       
   240                 Utils.SetValue( row, 4, aSheet, "=" + Utils.ColumnAndRowAsExcelIdentifier( row, 3 ) + "-" + Utils.ColumnAndRowAsExcelIdentifier( row, 2 ) );
       
   241             }
       
   242 
       
   243             // Spacer
       
   244             row++;
       
   245 
       
   246             {
       
   247                 long heapAllocSize1 = iEngine.Reconstructor1.Statistics.StatsAllocated.TypeSize;
       
   248                 long heapAllocSize2 = iEngine.Reconstructor2.Statistics.StatsAllocated.TypeSize;
       
   249                 row++;
       
   250                 Utils.SetValue( row, 1, aSheet, "Allocated Space" );
       
   251                 Utils.SetValue( row, 2, aSheet, heapAllocSize1.ToString() );
       
   252                 Utils.SetValue( row, 3, aSheet, heapAllocSize2.ToString() );
       
   253                 Utils.SetValue( row, 4, aSheet, "=" + Utils.ColumnAndRowAsExcelIdentifier( row, 3 ) + "-" + Utils.ColumnAndRowAsExcelIdentifier( row, 2 ) );
       
   254 
       
   255                 long heapAllocCount1 = iEngine.Reconstructor1.Statistics.StatsAllocated.TypeCount;
       
   256                 long heapAllocCount2 = iEngine.Reconstructor2.Statistics.StatsAllocated.TypeCount;
       
   257                 row++;
       
   258                 Utils.SetValue( row, 1, aSheet, "Allocated Cell Count" );
       
   259                 Utils.SetValue( row, 2, aSheet, heapAllocCount1.ToString() );
       
   260                 Utils.SetValue( row, 3, aSheet, heapAllocCount2.ToString() );
       
   261                 Utils.SetValue( row, 4, aSheet, "=" + Utils.ColumnAndRowAsExcelIdentifier( row, 3 ) + "-" + Utils.ColumnAndRowAsExcelIdentifier( row, 2 ) );
       
   262             }
       
   263 
       
   264             // Spacer
       
   265             row++;
       
   266 
       
   267             {
       
   268                 long heapAllocUnknownSize1 = iEngine.Reconstructor1.Statistics.StatsAllocated.TrackerUnknown.AssociatedMemory;
       
   269                 long heapAllocUnknownSize2 = iEngine.Reconstructor2.Statistics.StatsAllocated.TrackerUnknown.AssociatedMemory;
       
   270                 row++;
       
   271                 Utils.SetValue( row, 1, aSheet, "\"Unknown\" Allocated Space" );
       
   272                 Utils.SetValue( row, 2, aSheet, heapAllocUnknownSize1.ToString() );
       
   273                 Utils.SetValue( row, 3, aSheet, heapAllocUnknownSize2.ToString() );
       
   274                 Utils.SetValue( row, 4, aSheet, "=" + Utils.ColumnAndRowAsExcelIdentifier( row, 3 ) + "-" + Utils.ColumnAndRowAsExcelIdentifier( row, 2 ) );
       
   275 
       
   276                 long heapAllocUnknownCount1 = iEngine.Reconstructor1.Statistics.StatsAllocated.TrackerUnknown.AssociatedCellCount;
       
   277                 long heapAllocUnknownCount2 = iEngine.Reconstructor2.Statistics.StatsAllocated.TrackerUnknown.AssociatedCellCount;
       
   278                 row++;
       
   279                 Utils.SetValue( row, 1, aSheet, "\"Unknown\" Allocated Cell Count" );
       
   280                 Utils.SetValue( row, 2, aSheet, heapAllocUnknownCount1.ToString() );
       
   281                 Utils.SetValue( row, 3, aSheet, heapAllocUnknownCount2.ToString() );
       
   282                 Utils.SetValue( row, 4, aSheet, "=" + Utils.ColumnAndRowAsExcelIdentifier( row, 3 ) + "-" + Utils.ColumnAndRowAsExcelIdentifier( row, 2 ) );
       
   283             }
       
   284 
       
   285             // Spacer
       
   286             row++;
       
   287 
       
   288             {
       
   289                 long heapAllocDesSize1 = iEngine.Reconstructor1.Statistics.StatsAllocated.TrackerDescriptors.AssociatedMemory;
       
   290                 long heapAllocDesSize2 = iEngine.Reconstructor2.Statistics.StatsAllocated.TrackerDescriptors.AssociatedMemory;
       
   291                 row++;
       
   292                 Utils.SetValue( row, 1, aSheet, "Descriptor Allocated Space" );
       
   293                 Utils.SetValue( row, 2, aSheet, heapAllocDesSize1.ToString() );
       
   294                 Utils.SetValue( row, 3, aSheet, heapAllocDesSize2.ToString() );
       
   295                 Utils.SetValue( row, 4, aSheet, "=" + Utils.ColumnAndRowAsExcelIdentifier( row, 3 ) + "-" + Utils.ColumnAndRowAsExcelIdentifier( row, 2 ) );
       
   296 
       
   297                 long heapAllocDesCount1 = iEngine.Reconstructor1.Statistics.StatsAllocated.TrackerDescriptors.AssociatedCellCount;
       
   298                 long heapAllocDesCount2 = iEngine.Reconstructor2.Statistics.StatsAllocated.TrackerDescriptors.AssociatedCellCount;
       
   299                 row++;
       
   300                 Utils.SetValue( row, 1, aSheet, "Descriptor Allocated Cell Count" );
       
   301                 Utils.SetValue( row, 2, aSheet, heapAllocDesCount1.ToString() );
       
   302                 Utils.SetValue( row, 3, aSheet, heapAllocDesCount2.ToString() );
       
   303                 Utils.SetValue( row, 4, aSheet, "=" + Utils.ColumnAndRowAsExcelIdentifier( row, 3 ) + "-" + Utils.ColumnAndRowAsExcelIdentifier( row, 2 ) );
       
   304 
       
   305                 /*
       
   306                 using ( System.IO.StreamWriter w1 = new System.IO.StreamWriter( "O:\\desc1.txt", false ) )
       
   307                 {
       
   308                     foreach ( HeapCell c1 in iEngine.Reconstructor1.Statistics.StatsAllocated.TrackerDescriptors )
       
   309                     {
       
   310                         w1.WriteLine( c1.ToStringExtended() + " " + c1.DescriptorTextBeautified );
       
   311                     }
       
   312                 }
       
   313                 using ( System.IO.StreamWriter w2 = new System.IO.StreamWriter( "O:\\desc2.txt", false ) )
       
   314                 {
       
   315                     foreach ( HeapCell c2 in iEngine.Reconstructor2.Statistics.StatsAllocated.TrackerDescriptors )
       
   316                     {
       
   317                         w2.WriteLine( c2.ToStringExtended() + " " + c2.DescriptorTextBeautified );
       
   318                     }
       
   319                 }
       
   320                 */
       
   321             }
       
   322 
       
   323             // Spacer
       
   324             row++;
       
   325 
       
   326             {
       
   327                 long typeSize1 = iEngine.Reconstructor1.Statistics.StatsAllocated.TrackerSymbols.TypeSize;
       
   328                 long typeSize2 = iEngine.Reconstructor2.Statistics.StatsAllocated.TrackerSymbols.TypeSize;
       
   329                 row++;
       
   330                 Utils.SetValue( row, 1, aSheet, "\"With Symbols\" Allocated Space" );
       
   331                 Utils.SetValue( row, 2, aSheet, typeSize1.ToString() );
       
   332                 Utils.SetValue( row, 3, aSheet, typeSize2.ToString() );
       
   333                 Utils.SetValue( row, 4, aSheet, "=" + Utils.ColumnAndRowAsExcelIdentifier( row, 3 ) + "-" + Utils.ColumnAndRowAsExcelIdentifier( row, 2 ) );
       
   334 
       
   335                 long typeCount1 = iEngine.Reconstructor1.Statistics.StatsAllocated.TrackerSymbols.CellMatchCount;
       
   336                 long typeCount2 = iEngine.Reconstructor2.Statistics.StatsAllocated.TrackerSymbols.CellMatchCount;
       
   337                 row++;
       
   338                 Utils.SetValue( row, 1, aSheet, "\"With Symbols\" Allocated Cell Count" );
       
   339                 Utils.SetValue( row, 2, aSheet, typeCount1.ToString() );
       
   340                 Utils.SetValue( row, 3, aSheet, typeCount2.ToString() );
       
   341                 Utils.SetValue( row, 4, aSheet, "=" + Utils.ColumnAndRowAsExcelIdentifier( row, 3 ) + "-" + Utils.ColumnAndRowAsExcelIdentifier( row, 2 ) );
       
   342             }
       
   343 
       
   344             // Spacer
       
   345             row++;
       
   346             int freeRow = row;
       
   347 
       
   348             {
       
   349                 long heapFreeSize1 = iEngine.Reconstructor1.Statistics.StatsFree.TypeSize;
       
   350                 long heapFreeSize2 = iEngine.Reconstructor2.Statistics.StatsFree.TypeSize;
       
   351                 row++;
       
   352                 Utils.SetValue( row, 1, aSheet, "Free Space" );
       
   353                 Utils.SetValue( row, 2, aSheet, heapFreeSize1.ToString() );
       
   354                 Utils.SetValue( row, 3, aSheet, heapFreeSize2.ToString() );
       
   355                 Utils.SetValue( row, 4, aSheet, "=" + Utils.ColumnAndRowAsExcelIdentifier( row, 3 ) + "-" + Utils.ColumnAndRowAsExcelIdentifier( row, 2 ) );
       
   356 
       
   357                 long heapFreeCount1 = iEngine.Reconstructor1.Statistics.StatsFree.TypeCount;
       
   358                 long heapFreeCount2 = iEngine.Reconstructor2.Statistics.StatsFree.TypeCount;
       
   359                 row++;
       
   360                 Utils.SetValue( row, 1, aSheet, "Free Cell Count" );
       
   361                 Utils.SetValue( row, 2, aSheet, heapFreeCount1.ToString() );
       
   362                 Utils.SetValue( row, 3, aSheet, heapFreeCount2.ToString() );
       
   363                 Utils.SetValue( row, 4, aSheet, "=" + Utils.ColumnAndRowAsExcelIdentifier( row, 3 ) + "-" + Utils.ColumnAndRowAsExcelIdentifier( row, 2 ) );
       
   364             }
       
   365 
       
   366             // Spacer
       
   367             row++;
       
   368             row++;
       
   369             Utils.SetValue( row, 1, aSheet, "Symbol" );
       
   370             Utils.SetValue( row, 2, aSheet, "Heap 1" ).AddComment( "Associated cell count from: " + iEngine.Reconstructor1.SourceData.FileName );
       
   371             Utils.SetValue( row, 3, aSheet, "Heap 2" ).AddComment( "Associated cell count from: " + iEngine.Reconstructor2.SourceData.FileName );
       
   372             Utils.SetValue( row, 4, aSheet, "Delta" );
       
   373             Utils.MakeBoxedTitleRow( row, 4, aSheet, 0xFF0000 );
       
   374 
       
   375             row++;
       
   376             int firstSymbolRow = row;
       
   377 
       
   378             // Trackers for both heaps
       
   379             SymbolTrackingInfoCollection tracker1 = iEngine.Reconstructor1.Statistics.StatsAllocated.TrackerSymbols;
       
   380             SymbolTrackingInfoCollection tracker2 = iEngine.Reconstructor2.Statistics.StatsAllocated.TrackerSymbols;
       
   381 
       
   382             // We need a row for unknown items
       
   383             {
       
   384                 Utils.SetValue( row, 1, aSheet, "Unknown" );
       
   385                 int count1 = iEngine.Reconstructor1.Statistics.StatsAllocated.TrackerUnknown.AssociatedCellCount;
       
   386                 int count2 = iEngine.Reconstructor2.Statistics.StatsAllocated.TrackerUnknown.AssociatedCellCount;
       
   387                 Utils.SetValue( row, 2, aSheet, count1.ToString() );
       
   388                 Utils.SetValue( row, 3, aSheet, count2.ToString() );
       
   389                 Utils.SetValue( row, 4, aSheet, ( count2 - count1 ).ToString() );
       
   390                 row++;
       
   391             }
       
   392 
       
   393             // We need a row for descriptor items
       
   394             {
       
   395                 Utils.SetValue( row, 1, aSheet, "Descriptors" );
       
   396                 int count1 = iEngine.Reconstructor1.Statistics.StatsAllocated.TrackerDescriptors.AssociatedCellCount;
       
   397                 int count2 = iEngine.Reconstructor2.Statistics.StatsAllocated.TrackerDescriptors.AssociatedCellCount;
       
   398                 Utils.SetValue( row, 2, aSheet, count1.ToString() );
       
   399                 Utils.SetValue( row, 3, aSheet, count2.ToString() );
       
   400                 Utils.SetValue( row, 4, aSheet, ( count2 - count1 ).ToString() );
       
   401                 row++;
       
   402             }
       
   403 
       
   404             // Symbols from heap 1
       
   405             List<TrackingInfo> uniqueInHeap2 = new List<TrackingInfo>();
       
   406             foreach ( TrackingInfo info in tracker1 )
       
   407             {
       
   408                 System.Diagnostics.Debug.Assert( info.IsUnknownSymbolMatchItem == false );
       
   409 
       
   410                 int count1 = info.Count;
       
   411                 int count2 = 0;
       
   412                 TrackingInfo info2 = tracker2[ info.Symbol ];
       
   413                 if ( info2 != null )
       
   414                 {
       
   415                     count2 = info2.Count;
       
   416                 }
       
   417 
       
   418                 row++;
       
   419                 Utils.SetValue( row, 2, aSheet, count1.ToString() );
       
   420                 Utils.SetValue( row, 1, aSheet, info.Symbol.NameWithoutVTablePrefix );
       
   421                 Utils.SetValue( row, 3, aSheet, count2.ToString() );
       
   422                 Utils.SetValue( row, 4, aSheet, ( count2 - count1 ).ToString() );
       
   423 
       
   424                 // Must remove the item so we can spot any types that were new in heap 2
       
   425                 tracker2.Remove( info );
       
   426             }
       
   427 
       
   428             // The remaining items in tracker2 had no corresponding entries in tracker1
       
   429             foreach ( TrackingInfo info in tracker2 )
       
   430             {
       
   431                 System.Diagnostics.Debug.Assert( info.IsUnknownSymbolMatchItem == false );
       
   432                 row++;
       
   433                 Utils.SetValue( row, 1, aSheet, info.Symbol.NameWithoutVTablePrefix );
       
   434                 Utils.SetValue( row, 2, aSheet, "0" );
       
   435                 Utils.SetValue( row, 3, aSheet, info.Count.ToString() );
       
   436                 Utils.SetValue( row, 4, aSheet, info.Count.ToString() );
       
   437             }
       
   438 
       
   439             // Set the number format for the delta column
       
   440             Range allocRange = Utils.GetRangeByColumnAndRow( 2, 4, row, 4, aSheet );
       
   441             allocRange.NumberFormat = "[Red]0;[Blue]-0;[Black]0;";
       
   442 
       
   443             // Except for the free cells, which have the colour highlighting the other way around
       
   444             Range freeRange = Utils.GetRangeByColumnAndRow( freeRow, 4, freeRow + 1, 4, aSheet );
       
   445             freeRange.NumberFormat = "[Blue]0;[Red]-0;[Black]0;";
       
   446 
       
   447             // Sort by delta
       
   448             Excel.Range masterSortCell = (Excel.Range) aSheet.Cells[ 1, 4 ];
       
   449             Excel.Range range = Utils.GetRangeByColumnAndRow( firstSymbolRow, 1, row, 4, aSheet );
       
   450             range.Sort( masterSortCell.Columns[ 1, Type.Missing ], Microsoft.Office.Interop.Excel.XlSortOrder.xlDescending,
       
   451                         Type.Missing, Type.Missing, Microsoft.Office.Interop.Excel.XlSortOrder.xlDescending,
       
   452                         Type.Missing, Microsoft.Office.Interop.Excel.XlSortOrder.xlDescending, Microsoft.Office.Interop.Excel.XlYesNoGuess.xlNo,
       
   453                         Type.Missing, Type.Missing,
       
   454                         Microsoft.Office.Interop.Excel.XlSortOrientation.xlSortColumns,
       
   455                         Microsoft.Office.Interop.Excel.XlSortMethod.xlPinYin,
       
   456                         Microsoft.Office.Interop.Excel.XlSortDataOption.xlSortNormal,
       
   457                         Microsoft.Office.Interop.Excel.XlSortDataOption.xlSortNormal,
       
   458                         Microsoft.Office.Interop.Excel.XlSortDataOption.xlSortNormal );
       
   459 
       
   460             // Summation of deltas
       
   461             string sumForm = Utils.MakeSummationFormula( firstSymbolRow, row, 4, aSheet );
       
   462             Utils.SetValue( row + 2, 4, aSheet, sumForm );
       
   463 
       
   464             Utils.BoldColumn( 1, aSheet );
       
   465             Utils.AutoFitColumnNoMax( 1, aSheet );
       
   466         }
       
   467         
       
   468         private void ChangeToEnglishCulture()
       
   469         {
       
   470             System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
       
   471         }
       
   472         
       
   473         private void RestoreOriginalCulture()
       
   474         {
       
   475             System.Threading.Thread.CurrentThread.CurrentCulture = iOriginalCulture;
       
   476         }
       
   477         #endregion
       
   478 
       
   479         #region Internal callback methods
       
   480         #endregion
       
   481 
       
   482         #region Data members
       
   483         private readonly ComparsionEngine iEngine;
       
   484         private readonly string iFileName;
       
   485         private CultureInfo iOriginalCulture;
       
   486         private Application iExcelApp = null;
       
   487         private Workbook iWorkbook = null;
       
   488         private Worksheet iSummary = null;
       
   489         private int iCurrentPageIndex = 0;
       
   490         private List<PageBase> iPages = new List<PageBase>();
       
   491         #endregion
       
   492     }
       
   493 }