Fix diff-xls.js error reported from http://tortoisesvn.tigris.org/ds/viewMessage...
[TortoiseGit.git] / contrib / diff-scripts / diff-xls.js
blob0ef12c2c93e0ec2651326162693df8e38d526ceb
1 // extensions: xls;xlsx;xlsm;xlsb;xlam\r
2 //\r
3 // TortoiseSVN Diff script for Excel files\r
4 //\r
5 // Copyright (C) 2004-2008 the TortoiseSVN team\r
6 // This file is distributed under the same license as TortoiseSVN\r
7 //\r
8 // Last commit by:\r
9 // $Author$\r
10 // $Date$\r
11 // $Rev$\r
12 //\r
13 // Authors:\r
14 // Hiroki Najima <h.najima at gmail.com>, 2013\r
15 // Michael Joras <michael@joras.net>, 2008\r
16 // Suraj Barkale, 2006\r
17 //\r
19 // ----- configuration -----\r
20 // Fast mode switch\r
21 // Fast mode does not copy Worksheets but require opened base document at the same time.\r
22 var bFastMode = false;\r
24 // ----- constants -----\r
25 var vbCritical = 0x10;\r
26 var vbExclamation = 0x30;\r
27 //var vbInformation = 0x40;\r
29 var xlNone = -4142;\r
30 var xlMaximized = -4137;\r
31 var xlArrangeStyleHorizontal = -4128;\r
32 var xlCellValue = 1;\r
33 //var xlExpression = 2;\r
34 //var xlEqual = 3;\r
35 var xlNotEqual = 4;\r
37 //var vOffice95 = 7;\r
38 //var vOffice97 = 8;\r
39 //var vOffice2000 = 9;\r
40 //var vOffice2002 = 10;\r
41 var vOffice2003 = 11;\r
42 //var vOffice2007 = 12;\r
43 //var vOffice2010 = 14;\r
44 //var vOffice2013 = 15;\r
46 // ----- main -----\r
48 var aWarningMessages = Array();\r
50 var objArgs = WScript.Arguments;\r
51 if (objArgs.length < 2)\r
52 {\r
53     Abort("Usage: [CScript | WScript] diff-xls.js base.xls new.xls", "Invalid arguments");\r
54 }\r
56 var sBaseDoc = objArgs(0);\r
57 var sNewDoc = objArgs(1);\r
59 var objScript = new ActiveXObject("Scripting.FileSystemObject");\r
61 if (objScript.GetBaseName(sBaseDoc) === objScript.GetBaseName(sNewDoc))\r
62 {\r
63     Abort("File '" + sBaseDoc + "' and '" + sNewDoc + "' is same file name.\nCannot compare the documents.", "Same file name");\r
64 }\r
66 if (!objScript.FileExists(sBaseDoc))\r
67 {\r
68     Abort("File '" + sBaseDoc + "' does not exist.\nCannot compare the documents.", "File not found");\r
69 }\r
71 if (!objScript.FileExists(sNewDoc))\r
72 {\r
73     Abort("File '" + sNewDoc + "' does not exist.\nCannot compare the documents.", "File not found");\r
74 }\r
76 sBaseDoc = objScript.GetAbsolutePathName(sBaseDoc);\r
77 sNewDoc = objScript.GetAbsolutePathName(sNewDoc);\r
78 objScript = null;\r
80 var objExcelApp;\r
81 try\r
82 {\r
83     objExcelApp = WScript.CreateObject("Excel.Application");\r
84 }\r
85 catch (e)\r
86 {\r
87     Abort("You must have Excel installed to perform this operation.", "Excel Instantiation Failed");\r
88 }\r
89 var fExcelVersion = parseInt(objExcelApp.Version, 10);\r
91 // Open base Excel book\r
92 var objBaseWorkbook;\r
93 try\r
94 {\r
95     objBaseWorkbook = objExcelApp.Workbooks.Open(sBaseDoc, null, true);\r
96 }\r
97 catch (e)\r
98 {\r
99     Abort("Failed to open '" + sBaseDoc + "'\nIt might not be a valid Excel file.", "File open error");\r
102 // Open new Excel book\r
103 var objNewWorkbook;\r
104 try\r
106     objNewWorkbook = objExcelApp.Workbooks.Open(sNewDoc, null, true);\r
108 catch (e)\r
110     Abort("Failed to open '" + sNewDoc + "'\nIt might not be a valid Excel file.", "File open error");\r
113 // Show Excel window\r
114 objExcelApp.Visible = true;\r
116 // Arrange windows\r
117 if (objBaseWorkbook.ProtectWindows || objNewWorkbook.ProtectWindows)\r
119     StoreWarning("Unable to arrange windows because one or both Workbooks are protected.");\r
121 else\r
123     // Make windows a compare side by side view\r
124     if (fExcelVersion >= vOffice2003)\r
125     {\r
126         objExcelApp.Windows.CompareSideBySideWith(objExcelApp.Windows(2).Caption);\r
127     }\r
128     objExcelApp.Application.WindowState = xlMaximized;\r
129     objExcelApp.Windows.Arrange(xlArrangeStyleHorizontal);\r
132 if (!bFastMode && objNewWorkbook.ProtectWindows)\r
134     StoreWarning("Fall back to fast mode because " + objNewWorkbook.Name + " is protected.");\r
135     bFastMode = true;\r
138 // Mark differences in sNewDoc red\r
139 var length = objNewWorkbook.Worksheets.Count;\r
140 for (var i = 1; i <= length; i++)\r
142     var objBaseWorksheet = objBaseWorkbook.Worksheets(i);\r
143     var objNewWorksheet = objNewWorkbook.Worksheets(i);\r
145     UnhideWorksheet(objBaseWorksheet);\r
146     UnhideWorksheet(objNewWorksheet);\r
148     if (!bFastMode)\r
149     {\r
150         objBaseWorkbook.Sheets(i).Copy(null, objNewWorkbook.Sheets(objNewWorkbook.Sheets.Count));\r
151         var objDummyWorksheet = objNewWorkbook.Sheets(objNewWorkbook.Sheets.Count);\r
152         objDummyWorksheet.Name = "Dummy_for_Comparison" + i;\r
153         objDummyWorksheet.Visible = true;\r
154         if (fExcelVersion >= vOffice2003)\r
155         {\r
156             objDummyWorksheet.Tab.ColorIndex = 16;  // 16:Dark gray RGB(128,128,128)\r
157         }\r
158     }\r
160     if (objNewWorksheet.ProtectContents)\r
161     {\r
162         StoreWarning("Unable to mark differences to " +\r
163             ToAbsoluteReference(objNewWorksheet) +\r
164             " because the Worksheet is protected.");\r
165     }\r
166     else\r
167     {\r
168         objNewWorksheet.Cells.FormatConditions.Delete();\r
169         var sFormula;\r
170         if (bFastMode)\r
171         {\r
172             sFormula = "=INDIRECT(\"" + ToAbsoluteReference(objBaseWorksheet) + "!\"&ADDRESS(ROW(),COLUMN()))";\r
173         }\r
174         else\r
175         {\r
176             sFormula = "=INDIRECT(\"Dummy_for_Comparison" + i + "!\"&ADDRESS(ROW(),COLUMN()))";\r
177         }\r
178         var original_content = objNewWorksheet.Cells(1,1).Formula;\r
179         objNewWorksheet.Cells(1,1).Formula = sFormula;\r
180         sFormula = objNewWorksheet.Cells(1,1).FormulaLocal;\r
181         objNewWorksheet.Cells(1,1).Formula = original_content;\r
182         objNewWorksheet.Cells.FormatConditions.Add(xlCellValue, xlNotEqual, sFormula);\r
183         objNewWorksheet.Cells.FormatConditions(1).Interior.ColorIndex = 3;  // 3:Red RGB(128,0,0)\r
184     }\r
188 // Activate first Worksheet\r
189 objBaseWorkbook.Sheets(1).Activate();\r
190 objNewWorkbook.Sheets(1).Activate();\r
192 // Suppress save dialog if nothing changed\r
193 objBaseWorkbook.Saved = true;\r
194 objNewWorkbook.Saved = true;\r
196 // Show warnings if exist\r
197 ShowWarning();\r
199 WScript.Quit(0);\r
202 // ----- functions -----\r
204 // Show Message Dialog\r
205 // VBcript's MsgBox emulation\r
206 function MsgBox(sMessage, iButtons, sTitle)\r
208     var objShell = new ActiveXObject("WScript.Shell");\r
209     objShell.popup(sMessage, 0, sTitle, iButtons);\r
212 // Show an error message and quit script with cleanup Excel Application Object.\r
213 function Abort(sMessage, sTitle)\r
215     MsgBox(sMessage, vbCritical, sTitle);\r
216     if (objExcelApp)\r
217     {\r
218         objExcelApp.Quit();\r
219     }\r
220     WScript.Quit(1);\r
223 // Unhide the Worksheet if it is hidden.\r
224 // This also sets color to the tab, if Office2003 or later.\r
225 //  - 46(Orange)      : Hidden Worksheet\r
226 //  - xlNone(default) : Not hidden Worksheet\r
227 function UnhideWorksheet(objWorksheet)\r
229     if (objWorksheet.Visible)\r
230     {\r
231         if (fExcelVersion >= vOffice2003)\r
232         {\r
233             if (objWorksheet.Tab.ColorIndex !== xlNone)\r
234             {\r
235                 if (objWorksheet.Parent.ProtectStructure)\r
236                 {\r
237                     StoreWarning("Unable to set tab color to " +\r
238                         ToAbsoluteReference(objWorksheet) +\r
239                         " because the Workbook's structure is protected.");\r
240                 }\r
241                 else\r
242                 {\r
243                     objWorksheet.Tab.ColorIndex = xlNone;\r
244                 }\r
245             }\r
246         }\r
247     }\r
248     else\r
249     {\r
250         if (objWorksheet.Parent.ProtectStructure)\r
251         {\r
252             StoreWarning("Unable to unhide " +\r
253                 ToAbsoluteReference(objWorksheet) +\r
254                 " because the Workbook's structure is protected.");\r
255         }\r
256         else\r
257         {\r
258             objWorksheet.Visible = true;\r
259             if (fExcelVersion >= vOffice2003)\r
260             {\r
261                 objWorksheet.Tab.ColorIndex = 10;   // 10:Green RGB(0,128,0)\r
262             }\r
263         }\r
264     }\r
267 // Generate Absolute Reference Formula of Worksheet.\r
268 function ToAbsoluteReference(objWorksheet)\r
270     return "[" + objWorksheet.Parent.Name + "]" + objWorksheet.Name;\r
273 // Accumulate a warning message.\r
274 function StoreWarning(sMessage)\r
276     aWarningMessages[aWarningMessages.length] = sMessage;\r
279 // Show accumulated warning messages if exist.\r
280 // To avoid make huge message dialog, this limits message count to show.\r
281 function ShowWarning()\r
283     if (aWarningMessages.length === 0)\r
284     {\r
285         return;\r
286     }\r
287     var sMessage = "The following warnings occurred while processing.\n";\r
288     for (var i = 0; i < aWarningMessages.length; i++)\r
289     {\r
290         if (i >= 10)\r
291         {\r
292             sMessage += "... And more " + (aWarningMessages.length - i) + " messages";\r
293             break;\r
294         }\r
295         sMessage += "[" + (i + 1) + "] " + aWarningMessages[i] + "\n";\r
296     }\r
297     MsgBox(sMessage, vbExclamation, "Warning");\r