1VERSION 1.0 CLASS 2BEGIN 3 MultiUse = -1 'True 4END 5Attribute VB_Name = "MigrationAnalyser" 6Attribute VB_GlobalNameSpace = False 7Attribute VB_Creatable = False 8Attribute VB_PredeclaredId = False 9Attribute VB_Exposed = False 10'************************************************************************* 11' 12' Licensed to the Apache Software Foundation (ASF) under one 13' or more contributor license agreements. See the NOTICE file 14' distributed with this work for additional information 15' regarding copyright ownership. The ASF licenses this file 16' to you under the Apache License, Version 2.0 (the 17' "License"); you may not use this file except in compliance 18' with the License. You may obtain a copy of the License at 19' 20' http://www.apache.org/licenses/LICENSE-2.0 21' 22' Unless required by applicable law or agreed to in writing, 23' software distributed under the License is distributed on an 24' "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 25' KIND, either express or implied. See the License for the 26' specific language governing permissions and limitations 27' under the License. 28' 29'************************************************************************* 30 31Option Explicit 32 33'Class variables 34Private Enum HFIssueType 35 hfInline 36 hfShape 37 hfFrame 38End Enum 39 40Private Enum HFIssueLocation 41 hfHeader 42 hffooter 43End Enum 44 45 46Private Type ShapeInfo 47 top As Single 48 Height As Single 49End Type 50 51Private Type FrameInfo 52 Height As Single 53 VerticalPosition As Single 54End Type 55 56Private mAnalysis As DocumentAnalysis 57Private mOdd As Boolean 58Private mbFormFieldErrorLogged As Boolean 59Private mbRefFormFieldErrorLogged As Boolean 60 61'***ADDING-ISSUE: Use Following Skeleton as Guideline for Adding Issue 62' For complete list of all RID_STR_... for Issues (IssueType), SubIssues (SubType) and Attributes refer to: 63' word_res.bas and common_res.bas 64' 65' For complete list of all CID_... for Issue Categories(IssueID) and 66' CSTR_... for XML Issues (IssueTypeXML) and XML SubIssues (SubTypeXML) refer to: 67' ApplicationSpecific.bas and CommonMigrationAnalyser.bas 68' 69' You should not have to add any new Issue Categories or matching IssueTypes, only new SubIssues 70Sub Analyze_SKELETON() 71 On Error GoTo HandleErrors 72 Dim currentFunctionName As String 73 currentFunctionName = "Analyze_SKELETON" 74 Dim myIssue As IssueInfo 75 Set myIssue = New IssueInfo 76 77 With myIssue 78 .IssueID = CID_VBA_MACROS 'Issue Category 79 .IssueType = RID_STR_COMMON_ISSUE_VBA_MACROS 'Issue String 80 .SubType = RID_STR_COMMON_SUBISSUE_PROPERTIES 'SubIssue String 81 .Location = .CLocationDocument 'Location string 82 83 .IssueTypeXML = CSTR_ISSUE_VBA_MACROS 'Non localised XML Issue String 84 .SubTypeXML = CSTR_SUBISSUE_PROPERTIES 'Non localised XML SubIssue String 85 .locationXML = .CXMLLocationDocument 'Non localised XML location 86 87 .SubLocation = 0 'if not set will default to RID_STR_NOT_AVAILABLE_SHORTHAND 88 .Line = 0 'if not set will default to RID_STR_NOT_AVAILABLE_SHORTHAND 89 .column = 0 'if not set will default to RID_STR_NOT_AVAILABLE_SHORTHAND 90 91 ' Add as many Attribute Value pairs as needed 92 ' Note: following must always be true - Attributes.Count = Values.Count 93 .Attributes.Add "AAA" 94 .Values.Add "foobar" 95 96 ' Use AddIssueDetailsNote to add notes to the Issue Details if required 97 ' Public Sub AddIssueDetailsNote(myIssue As IssueInfo, noteNum As Long, noteStr As String, _ 98 ' Optional preStr As String = RID_STR_COMMON_NOTE_PRE) 99 ' Where preStr is prepended to the output, with "Note" as the default 100 AddIssueDetailsNote myIssue, 0, RID_STR_COMMON_NOTE_DOCUMENT_PROPERTIES_LOST 101 102 'Only put this in if you have a preparation function added for this issue in CommonPreparation 103 'or Preparation - NUll can be replaced with any variant if you want to pass info to the Prepare fnc 104 Call DoPreparation(mAnalysis, myIssue, "", Null, Null) 105 106 mAnalysis.IssuesCountArray(CID_VBA_MACROS) = _ 107 mAnalysis.IssuesCountArray(CID_VBA_MACROS) + 1 108 End With 109 110 mAnalysis.Issues.Add myIssue 111 112FinalExit: 113 Set myIssue = Nothing 114 Exit Sub 115 116HandleErrors: 117 WriteDebug currentFunctionName & " : " & mAnalysis.name & ": " & Err.Number & " " & Err.Description & " " & Err.Source 118 Resume FinalExit 119End Sub 120 121Sub DoAnalyse(fileName As String, userFormTypesDict As Scripting.Dictionary, _ 122 startDir As String, storeToDir As String, fso As FileSystemObject) 123 On Error GoTo HandleErrors 124 Dim currentFunctionName As String 125 currentFunctionName = "DoAnalyse" 126 mAnalysis.name = fileName 127 Dim aDoc As Document 128 Dim bUnprotectError As Boolean 129 mAnalysis.TotalIssueTypes = CTOTAL_CATEGORIES 130 mbFormFieldErrorLogged = False 131 mbRefFormFieldErrorLogged = False 132 133 'Turn off any AutoExce macros before loading the Word doc 134 On Error Resume Next ' Ignore errors on setting 135 WordBasic.DisableAutoMacros 1 136 On Error GoTo HandleErrors 137 138 Dim myPassword As String 139 myPassword = GetDefaultPassword 140 141 'Always skip password protected documents 142 'If IsSkipPasswordDocs() Then 143 Dim aPass As String 144 If myPassword <> "" Then 145 aPass = myPassword 146 Else 147 aPass = "xoxoxoxoxo" 148 End If 149 150 On Error Resume Next 151 Set aDoc = Documents.Open(fileName, False, False, False, _ 152 aPass, aPass, False, aPass, aPass, wdOpenFormatAuto, _ 153 msoEncodingAutoDetect, False) 154 If Err.Number = 5408 Then 155 ' if password protected, try open readonly next 156 Set aDoc = Documents.Open(fileName, False, True, False, _ 157 aPass, aPass, False, aPass, aPass, wdOpenFormatAuto, _ 158 msoEncodingAutoDetect, False) 159 End If 160 If Err.Number = 5408 Then 161 HandleProtectedDocInvalidPassword mAnalysis, _ 162 "User entered Invalid Document Password, further analysis not possible", fso 163 Analyze_Password_Protection True, False 164 GoTo FinalExit 165 ElseIf (Err.Number <> 0) Then 166 GoTo HandleErrors 167 End If 168 169 On Error GoTo HandleErrors 170 171 If aDoc Is Nothing Then GoTo FinalExit 172 173 'Do Analysis 174 Analyze_Password_Protection aDoc.HasPassword, aDoc.WriteReserved 175 Analyze_Document_Protection aDoc 176 177 If aDoc.ProtectionType <> wdNoProtection Then 178 If myPassword <> "" Then 179 aDoc.Unprotect (myPassword) 180 Else 181 aDoc.Unprotect 182 End If 183 End If 184 185 'Set Doc Properties 186 SetDocProperties mAnalysis, aDoc, fso 187 188ContinueFromUnprotectError: 189 190 Analyze_Tables_TablesInTables aDoc 191 Analyze_Tables_Borders aDoc 192 Analyze_TOA aDoc 193 If Not bUnprotectError Then 194 Analyze_FieldAndFormFieldIssues aDoc 195 End If 196 Analyze_OLEEmbedded aDoc 197 Analyze_MailMerge_DataSource aDoc 198 Analyze_Macros mAnalysis, userFormTypesDict, aDoc 199 'Analyze_Numbering aDoc, mAnalysis 200 'Analyze_NumberingTabs aDoc, mAnalysis 201 202 ' Doc Preparation only 203 ' Save document with any prepared issues under <storeToDir>\prepared\<source doc name> 204 If mAnalysis.PreparableIssuesCount > 0 And CheckDoPrepare Then 205 Dim preparedFullPath As String 206 preparedFullPath = GetPreparedFullPath(mAnalysis.name, startDir, storeToDir, fso) 207 If preparedFullPath <> "" Then 208 If fso.FileExists(preparedFullPath) Then 209 fso.DeleteFile preparedFullPath, True 210 End If 211 If fso.FolderExists(fso.GetParentFolderName(preparedFullPath)) Then 212 aDoc.SaveAs preparedFullPath 213 End If 214 End If 215 End If 216 217 'DebugMacroInfo 218 219FinalExit: 220 221 222 If Not aDoc Is Nothing Then 'If Not IsEmpty(aDoc) Then 223 aDoc.Close (False) 224 End If 225 Set aDoc = Nothing 226 227 Exit Sub 228 229HandleErrors: 230 ' MsgBox currentFunctionName & " : " & fileName & ": " & Err.Number & " " & Err.Description & " " & Err.Source 231 ' Handle Password error on Doc Open, Modify and Cancel 232 If Err.Number = 5408 Or Err.Number = 4198 Then 233 WriteDebug currentFunctionName & " : " & fileName & ": " & _ 234 "User entered Invalid Document Password - " & Err.Number & " " & Err.Description & " " & Err.Source 235 HandleProtectedDocInvalidPassword mAnalysis, _ 236 "User entered Invalid Document Password, further analysis not possible", fso 237 Resume FinalExit 238 ElseIf Err.Number = 5485 Then 239 ' Handle Password error on Unprotect Doc 240 WriteDebug currentFunctionName & " : " & fileName & ": " & _ 241 "User entered Invalid Document Part Password, Analysis of doc will continue but will skip analysis of:" & _ 242 "Forms, Comments, Headers & Footers and Table cell spanning issues - " & Err.Number & " " & Err.Description & " " & Err.Source 243 HandleProtectedDocInvalidPassword mAnalysis, _ 244 "User entered Invalid Document Part Password, Analysis of doc will continue but will skip analysis of:" & vbLf & _ 245 "Forms, Comments, Headers & Footers and Table cell spanning issues", fso 246 bUnprotectError = True 247 'wdAllowOnlyComments, wdAllowOnlyFormFields, wdAllowOnlyRevisions 248 Resume ContinueFromUnprotectError 249 End If 250 mAnalysis.Application = RID_STR_COMMON_CANNOT_OPEN 251 WriteDebug currentFunctionName & " : " & fileName & ": " & Err.Number & " " & Err.Description & " " & Err.Source 252 Resume FinalExit 253End Sub 254 255Sub DebugMacroInfo() 256 MsgBox "TotalNumLines: " & mAnalysis.MacroTotalNumLines & vbLf & _ 257 "NumUserForms: " & mAnalysis.MacroNumUserForms & vbLf & _ 258 "NumUserFormControls: " & mAnalysis.MacroNumUserFormControls & vbLf & _ 259 "NumUserFormControlTypes: " & mAnalysis.MacroNumUserFormControlTypes & vbLf & _ 260 "NumExternalRefs: " & mAnalysis.MacroNumExternalRefs & vbLf & _ 261 "MacroNumFieldsUsingMacros: " & mAnalysis.MacroNumFieldsUsingMacros & vbLf & _ 262 "NumOLEControls: " & mAnalysis.MacroNumOLEControls & vbLf & _ 263 "MacroOverallClass: " & getDocOverallMacroClassAsString(mAnalysis.MacroOverallClass) 264End Sub 265 266Sub SetDocProperties(docAnalysis As DocumentAnalysis, doc As Document, fso As FileSystemObject) 267 On Error GoTo HandleErrors 268 Dim currentFunctionName As String 269 currentFunctionName = "SetProperties" 270 Dim f As File 271 Set f = fso.GetFile(docAnalysis.name) 272 273 docAnalysis.PageCount = doc.ComputeStatistics(wdStatisticPages) 274 docAnalysis.Accessed = f.DateLastAccessed 275 276 On Error Resume Next 'Some apps may not support all props 277 docAnalysis.Application = getAppSpecificApplicationName & " " & Application.Version 278 'docAnalysis.Application = doc.BuiltinDocumentProperties(wdPropertyAppName) 279 'If InStr(docAnalysis.Application, "Microsoft") = 1 Then 280 ' docAnalysis.Application = Mid(docAnalysis.Application, Len("Microsoft") + 2) 281 'End If 282 'If InStr(Len(docAnalysis.Application) - 2, docAnalysis.Application, ".") = 0 Then 283 ' docAnalysis.Application = docAnalysis.Application & " " & Application.Version 284 'End If 285 286 docAnalysis.Created = _ 287 doc.BuiltInDocumentProperties(wdPropertyTimeCreated) 288 docAnalysis.Modified = _ 289 doc.BuiltInDocumentProperties(wdPropertyTimeLastSaved) 290 docAnalysis.Printed = _ 291 doc.BuiltInDocumentProperties(wdPropertyTimeLastPrinted) 292 docAnalysis.SavedBy = _ 293 doc.BuiltInDocumentProperties(wdPropertyLastAuthor) 294 docAnalysis.Revision = _ 295 val(doc.BuiltInDocumentProperties(wdPropertyRevision)) 296 docAnalysis.Template = _ 297 fso.GetFileName(doc.BuiltInDocumentProperties(wdPropertyTemplate)) 298 299FinalExit: 300 Set f = Nothing 301 Exit Sub 302 303HandleErrors: 304 WriteDebug currentFunctionName & " : " & mAnalysis.name & ": " & Err.Number & " " & Err.Description & " " & Err.Source 305 Resume FinalExit 306End Sub 307 308'Limitation: Detect first level table in tables, does not detect further nesting 309'Can do so if required 310Sub Analyze_Tables_TablesInTables(currDoc As Document) 311 On Error GoTo HandleErrors 312 Dim currentFunctionName As String 313 currentFunctionName = "Analyze_Tables_TablesInTables" 314 Dim myTopTable As Table 315 Dim myInnerTable As Table 316 Dim myIssue As IssueInfo 317 318 For Each myTopTable In currDoc.Tables 319 For Each myInnerTable In myTopTable.Tables 320 Dim logString As String 321 Dim myRng As Range 322 Dim startpage As Long 323 Dim startRow As Long 324 Dim StartColumn As Long 325 Dim details As String 326 327 Set myIssue = New IssueInfo 328 Set myRng = myInnerTable.Range 329 myRng.start = myRng.End 330 startpage = myRng.Information(wdActiveEndPageNumber) 331 startRow = myRng.Information(wdStartOfRangeRowNumber) 332 StartColumn = myRng.Information(wdStartOfRangeColumnNumber) 333 334 With myIssue 335 .IssueID = CID_TABLES 336 .IssueType = RID_STR_WORD_ISSUE_TABLES 337 .SubType = RID_STR_WORD_SUBISSUE_NESTED_TABLES 338 .Location = .CLocationPage 339 .SubLocation = startpage 340 341 .IssueTypeXML = CSTR_ISSUE_TABLES 342 .SubTypeXML = CSTR_SUBISSUE_NESTED_TABLES 343 .locationXML = .CXMLLocationPage 344 345 .Attributes.Add RID_STR_WORD_ATTRIBUTE_OUTER_TABLE 346 .Values.Add myTopTable.Rows.count & "x" & myTopTable.Columns.count 347 .Attributes.Add RID_STR_WORD_ATTRIBUTE_INNER_TABLE 348 .Values.Add myInnerTable.Rows.count & "x" & myInnerTable.Columns.count 349 .Attributes.Add RID_STR_WORD_ATTRIBUTE_START_ROW 350 .Values.Add startRow 351 .Attributes.Add RID_STR_WORD_ATTRIBUTE_START_COL 352 .Values.Add StartColumn 353 AddIssueDetailsNote myIssue, 0, RID_STR_WORD_NOTE_NESTED_TABLE_WILL_BE_LOST 354 355 mAnalysis.IssuesCountArray(CID_TABLES) = _ 356 mAnalysis.IssuesCountArray(CID_TABLES) + 1 357 End With 358 359 mAnalysis.Issues.Add myIssue 360 Set myIssue = Nothing 361 Set myRng = Nothing 362 Next 363 Next 364 Exit Sub 365HandleErrors: 366 WriteDebug currentFunctionName & " : " & mAnalysis.name & ": " & Err.Number & " " & Err.Description & " " & Err.Source 367End Sub 368 369Sub Analyze_Document_Protection(currDoc As Document) 370 On Error GoTo HandleErrors 371 Dim currentFunctionName As String 372 currentFunctionName = "Analyze_Document_Protection" 373 If currDoc.ProtectionType = wdNoProtection Then 374 Exit Sub 375 End If 376 377 Dim myIssue As IssueInfo 378 Set myIssue = New IssueInfo 379 380 With myIssue 381 .IssueID = CID_CONTENT_AND_DOCUMENT_PROPERTIES 382 .IssueType = RID_STR_COMMON_ISSUE_CONTENT_AND_DOCUMENT_PROPERTIES 383 .SubType = RID_STR_COMMON_SUBISSUE_DOCUMENT_PARTS_PROTECTION 384 .Location = .CLocationDocument 385 386 .IssueTypeXML = CSTR_ISSUE_CONTENT_DOCUMENT_PROPERTIES 387 .SubTypeXML = CSTR_SUBISSUE_DOCUMENT_PARTS_PROTECTION 388 .locationXML = .CXMLLocationDocument 389 390 .Attributes.Add RID_STR_WORD_ATTRIBUTE_PROTECTION 391 Select Case currDoc.ProtectionType 392 Case wdAllowOnlyComments 393 .Values.Add RID_STR_WORD_ATTRIBUTE_ALLOW_ONLY_COMMENTS 394 Case wdAllowOnlyFormFields 395 .Values.Add RID_STR_WORD_ATTRIBUTE_ALLOW_ONLY_FORM_FIELDS 396 Case wdAllowOnlyRevisions 397 .Values.Add RID_STR_WORD_ATTRIBUTE_ALLOW_ONLY_REVISIONS 398 Case Else 399 .Values.Add RID_STR_COMMON_ATTRIBUTE_UNKNOWN 400 End Select 401 402 mAnalysis.IssuesCountArray(CID_CONTENT_AND_DOCUMENT_PROPERTIES) = _ 403 mAnalysis.IssuesCountArray(CID_CONTENT_AND_DOCUMENT_PROPERTIES) + 1 404 End With 405 406 mAnalysis.Issues.Add myIssue 407FinalExit: 408 Set myIssue = Nothing 409 Exit Sub 410 411HandleErrors: 412 WriteDebug currentFunctionName & " : " & mAnalysis.name & ": " & Err.Number & " " & Err.Description & " " & Err.Source 413 Resume FinalExit 414End Sub 415 416Sub Analyze_Password_Protection(bHasPassword As Boolean, bWriteReserved As Boolean) 417 On Error GoTo HandleErrors 418 Dim currentFunctionName As String 419 currentFunctionName = "Analyze_Password_Protection" 420 Dim myIssue As IssueInfo 421 422 If bHasPassword Or bWriteReserved Then 423 Set myIssue = New IssueInfo 424 425 With myIssue 426 .IssueID = CID_CONTENT_AND_DOCUMENT_PROPERTIES 427 .IssueType = RID_STR_COMMON_ISSUE_CONTENT_AND_DOCUMENT_PROPERTIES 428 .SubType = RID_STR_COMMON_SUBISSUE_PASSWORDS_PROTECTION 429 .Location = .CLocationDocument 430 431 .IssueTypeXML = CSTR_ISSUE_CONTENT_DOCUMENT_PROPERTIES 432 .SubTypeXML = CSTR_SUBISSUE_PASSWORDS_PROTECTION 433 .locationXML = .CXMLLocationDocument 434 435 If bHasPassword Then 436 .Attributes.Add RID_STR_WORD_ATTRIBUTE_PASSWORD_TO_OPEN 437 .Values.Add RID_STR_WORD_ATTRIBUTE_SET 438 End If 439 If bWriteReserved Then 440 .Attributes.Add RID_STR_WORD_ATTRIBUTE_PASSWORD_TO_MODIFY 441 .Values.Add RID_STR_WORD_ATTRIBUTE_SET 442 End If 443 444 mAnalysis.IssuesCountArray(CID_CONTENT_AND_DOCUMENT_PROPERTIES) = _ 445 mAnalysis.IssuesCountArray(CID_CONTENT_AND_DOCUMENT_PROPERTIES) + 1 446 End With 447 448 mAnalysis.Issues.Add myIssue 449 End If 450FinalExit: 451 Set myIssue = Nothing 452 Exit Sub 453 454HandleErrors: 455 WriteDebug currentFunctionName & " : " & mAnalysis.name & ": " & Err.Number & " " & Err.Description & " " & Err.Source 456 Resume FinalExit 457End Sub 458 459Sub Analyze_OLEEmbedded(currDoc As Document) 460 On Error GoTo HandleErrors 461 Dim currentFunctionName As String 462 currentFunctionName = "Analyze_OLEEmbedded" 463 464 ' Handle Inline Shapes 465 Dim aILShape As InlineShape 466 For Each aILShape In currDoc.InlineShapes 467 Analyze_OLEEmbeddedSingleInlineShape aILShape 468 Next aILShape 469 470 ' Handle Shapes 471 Dim aShape As Shape 472 For Each aShape In currDoc.Shapes 473 Analyze_OLEEmbeddedSingleShape mAnalysis, aShape, _ 474 Selection.Information(wdActiveEndPageNumber) 475 Analyze_Lines mAnalysis, aShape, _ 476 Selection.Information(wdActiveEndPageNumber) 477 Analyze_Transparency mAnalysis, aShape, _ 478 Selection.Information(wdActiveEndPageNumber) 479 Analyze_Gradients mAnalysis, aShape, _ 480 Selection.Information(wdActiveEndPageNumber) 481 Next aShape 482 483 Exit Sub 484 485HandleErrors: 486 WriteDebug currentFunctionName & " : " & mAnalysis.name & ": " & Err.Number & " " & Err.Description & " " & Err.Source 487End Sub 488 489 490'WdInlineShapeType constants: 491'wdInlineShapeEmbeddedOLEObject, wdInlineShapeHorizontalLine, wdInlineShapeLinkedOLEObject, 492'wdInlineShapeLinkedPicture, wdInlineShapeLinkedPictureHorizontalLine, wdInlineShapeOLEControlObject, 493'wdInlineShapeOWSAnchor, wdInlineShapePicture, wdInlineShapePictureBullet, 494'wdInlineShapePictureHorizontalLine, wdInlineShapeScriptAnchor 495 496Sub Analyze_OLEEmbeddedSingleInlineShape(aILShape As InlineShape) 497 On Error GoTo HandleErrors 498 Dim currentFunctionName As String 499 currentFunctionName = "Analyze_OLEEmbeddedSingleInlineShape" 500 Dim myIssue As IssueInfo 501 Dim bOleObject As Boolean 502 Dim TypeAsString As String 503 Dim XMLTypeAsString As String 504 Dim objName As String 505 506 bOleObject = (aILShape.Type = wdInlineShapeEmbeddedOLEObject) Or _ 507 (aILShape.Type = wdInlineShapeLinkedOLEObject) Or _ 508 (aILShape.Type = wdInlineShapeOLEControlObject) 509 510 If Not bOleObject Then Exit Sub 511 512 aILShape.Select 513 Select Case aILShape.Type 514 Case wdInlineShapeOLEControlObject 515 TypeAsString = RID_STR_COMMON_OLE_CONTROL 516 XMLTypeAsString = CSTR_SUBISSUE_OLE_CONTROL 517 Case wdInlineShapeEmbeddedOLEObject 518 TypeAsString = RID_STR_COMMON_OLE_EMBEDDED 519 XMLTypeAsString = CSTR_SUBISSUE_OLE_EMBEDDED 520 Case wdInlineShapeLinkedOLEObject 521 TypeAsString = RID_STR_COMMON_OLE_LINKED 522 XMLTypeAsString = CSTR_SUBISSUE_OLE_LINKED 523 Case Else 524 TypeAsString = RID_STR_COMMON_OLE_UNKNOWN 525 XMLTypeAsString = CSTR_SUBISSUE_OLE_UNKNOWN 526 End Select 527 528 Set myIssue = New IssueInfo 529 With myIssue 530 .IssueID = CID_PORTABILITY 531 .IssueType = RID_STR_COMMON_ISSUE_PORTABILITY 532 .SubType = TypeAsString 533 .Location = .CLocationPage 534 .SubLocation = Selection.Information(wdActiveEndPageNumber) 535 536 .IssueTypeXML = CSTR_ISSUE_PORTABILITY 537 .SubTypeXML = XMLTypeAsString 538 .locationXML = .CXMLLocationPage 539 540 .Line = Selection.Information(wdFirstCharacterLineNumber) 541 .column = Selection.Information(wdFirstCharacterColumnNumber) 542 543 DoEvents 544 If aILShape.Type = wdInlineShapeEmbeddedOLEObject Or _ 545 aILShape.Type = wdInlineShapeOLEControlObject Then 546 547 'If Object is invalid can get automation server hanging 548 Dim tmpStr As String 549 On Error Resume Next 550 tmpStr = aILShape.OLEFormat.Object 551 If Err.Number = 0 Then 552 .Attributes.Add RID_STR_COMMON_ATTRIBUTE_OBJECT_TYPE 553 .Values.Add aILShape.OLEFormat.ProgID 554 Else 555 Err.Clear 556 tmpStr = aILShape.OLEFormat.ClassType 557 If Err.Number = 0 Then 558 .Attributes.Add RID_STR_COMMON_ATTRIBUTE_OBJECT_TYPE 559 .Values.Add aILShape.OLEFormat.ClassType 560 Else 561 .Attributes.Add RID_STR_COMMON_ATTRIBUTE_OBJECT_TYPE 562 .Values.Add RID_STR_COMMON_NA 563 End If 564 End If 565 566 If aILShape.Type = wdInlineShapeOLEControlObject Then 567 mAnalysis.MacroNumOLEControls = 1 + mAnalysis.MacroNumOLEControls 568 End If 569 570 objName = aILShape.OLEFormat.Object.name 571 If Err.Number = 0 Then 572 .Attributes.Add RID_STR_COMMON_ATTRIBUTE_OBJECT_NAME 573 .Values.Add objName 574 End If 575 On Error GoTo HandleErrors 576 End If 577 If aILShape.Type = wdInlineShapeLinkedOLEObject Then 578 .Attributes.Add RID_STR_COMMON_ATTRIBUTE_SOURCE 579 .Values.Add aILShape.LinkFormat.SourceFullName 580 End If 581 582 mAnalysis.IssuesCountArray(CID_PORTABILITY) = _ 583 mAnalysis.IssuesCountArray(CID_PORTABILITY) + 1 584 End With 585 586 mAnalysis.Issues.Add myIssue 587 588FinalExit: 589 Set myIssue = Nothing 590 Exit Sub 591 592HandleErrors: 593 WriteDebugLevelTwo currentFunctionName & " : " & mAnalysis.name & ": " & Err.Number & " " & Err.Description & " " & Err.Source 594 Resume FinalExit 595End Sub 596 597'Appears to be picked up by other OLE analysis code - the Shapes are actually field codes 598'So I get double reporting if I use this as well. 599Sub Analyze_OLEFields(myField As Field) 600 On Error GoTo HandleErrors 601 Dim currentFunctionName As String 602 currentFunctionName = "Analyze_OLEFields" 603 Dim myIssue As IssueInfo 604 Dim bOleObject As Boolean 605 Dim TypeAsString As String 606 Dim XMLTypeAsString As String 607 608 bOleObject = (myField.Type = wdFieldOCX) 609 610 If Not bOleObject Then Exit Sub 611 612 myField.Select 613 Select Case myField.Type 614 Case wdFieldLink 615 TypeAsString = RID_STR_COMMON_OLE_FIELD_LINK 616 XMLTypeAsString = CSTR_SUBISSUE_OLE_FIELD_LINK 617 Case Else 618 TypeAsString = RID_STR_COMMON_OLE_UNKNOWN 619 XMLTypeAsString = CSTR_SUBISSUE_OLE_UNKNOWN 620 End Select 621 Set myIssue = New IssueInfo 622 With myIssue 623 .IssueID = CID_PORTABILITY 624 .IssueType = RID_STR_COMMON_ISSUE_PORTABILITY 625 .SubType = TypeAsString 626 .Location = .CLocationPage 627 .SubLocation = Selection.Information(wdActiveEndPageNumber) 628 629 .IssueTypeXML = CSTR_ISSUE_PORTABILITY 630 .SubTypeXML = XMLTypeAsString 631 .locationXML = .CXMLLocationPage 632 633 .Line = Selection.Information(wdFirstCharacterLineNumber) 634 .column = Selection.Information(wdFirstCharacterColumnNumber) 635 .Attributes.Add RID_STR_COMMON_ATTRIBUTE_OBJECT_TYPE 636 .Values.Add myField.OLEFormat.ClassType 637 638 If myField.Type = wdFieldLink Then 639 .Attributes.Add RID_STR_WORD_ATTRIBUTE_LINK 640 .Values.Add myField.LinkFormat.SourceFullName 641 End If 642 mAnalysis.IssuesCountArray(CID_PORTABILITY) = _ 643 mAnalysis.IssuesCountArray(CID_PORTABILITY) + 1 644 End With 645 mAnalysis.Issues.Add myIssue 646 647 Set myIssue = Nothing 648 649 Exit Sub 650 651HandleErrors: 652 Set myIssue = Nothing 653 WriteDebug currentFunctionName & " : " & mAnalysis.name & ": " & Err.Number & " " & Err.Description & " " & Err.Source 654End Sub 655 656Sub Analyze_MailMergeField(myField As Field) 657 On Error GoTo HandleErrors 658 Dim currentFunctionName As String 659 currentFunctionName = "Analyze_MailMergeField" 660 Dim myIssue As IssueInfo 661 Dim TypeAsString As String 662 Dim bProblemMailMergeField As Boolean 663 664 bProblemMailMergeField = _ 665 (myField.Type = wdFieldFillIn) Or _ 666 (myField.Type = wdFieldAsk) Or _ 667 (myField.Type = wdFieldMergeRec) Or _ 668 (myField.Type = wdFieldMergeField) Or _ 669 (myField.Type = wdFieldNext) Or _ 670 (myField.Type = wdFieldRevisionNum) Or _ 671 (myField.Type = wdFieldSequence) Or _ 672 (myField.Type = wdFieldAutoNum) Or _ 673 (myField.Type = wdFieldAutoNumOutline) Or _ 674 (myField.Type = wdFieldAutoNumLegal) 675 676 If bProblemMailMergeField Then 677 'Some of the following are numbering fields and need to be broken out into a separate function. See migration guide. 678 679 Select Case myField.Type 680 Case wdFieldFillIn 681 TypeAsString = RID_STR_WORD_ENUMERATION_MAILMERGE_FILL_IN 682 Case wdFieldAsk 683 TypeAsString = RID_STR_WORD_ENUMERATION_MAILMERGE_ASK 684 Case wdFieldMergeRec 685 TypeAsString = RID_STR_WORD_ENUMERATION_MAILMERGE_MERGE_RECORDS 686 Case wdFieldMergeField 687 TypeAsString = RID_STR_WORD_ENUMERATION_MAILMERGE_MERGE_FIELDS 688 Case wdFieldNext 689 TypeAsString = RID_STR_WORD_ENUMERATION_MAILMERGE_NEXT 690 Case wdFieldRevisionNum 691 TypeAsString = RID_STR_WORD_ENUMERATION_MAILMERGE_REVISION_NUMBER 692 Case wdFieldSequence 693 TypeAsString = RID_STR_WORD_ENUMERATION_MAILMERGE_SEQUENCE 694 Case wdFieldAutoNum 695 TypeAsString = RID_STR_WORD_ENUMERATION_MAILMERGE_AUTO_NUMBER 696 Case wdFieldAutoNumOutline 697 TypeAsString = RID_STR_WORD_ENUMERATION_MAILMERGE_AUTO_NUMBER_OUTLINE 698 Case wdFieldAutoNumLegal 699 TypeAsString = RID_STR_WORD_ENUMERATION_MAILMERGE_AUTO_NUMBER_LEGAL 700 Case Else 701 TypeAsString = RID_STR_WORD_ENUMERATION_MAILMERGE_FIELD_NAME_NOT_KNOWN 702 End Select 703 704 Set myIssue = New IssueInfo 705 myField.Select 706 With myIssue 707 .IssueID = CID_FIELDS 708 .IssueType = RID_STR_WORD_ISSUE_FIELDS 709 .SubType = RID_STR_WORD_SUBISSUE_MAILMERGE_FIELD 710 .Location = .CLocationPage 711 712 .IssueTypeXML = CSTR_ISSUE_FIELDS 713 .SubTypeXML = CSTR_SUBISSUE_MAILMERGE_FIELD 714 .locationXML = .CXMLLocationPage 715 716 .SubLocation = Selection.Information(wdActiveEndPageNumber) 717 .Line = Selection.Information(wdFirstCharacterLineNumber) 718 .column = Selection.Information(wdFirstCharacterColumnNumber) 719 720 .Attributes.Add RID_STR_COMMON_ATTRIBUTE_NAME 721 .Values.Add TypeAsString 722 If myField.Code.Text <> "" Then 723 .Attributes.Add RID_STR_WORD_ATTRIBUTE_TEXT 724 .Values.Add myField.Code.Text 725 End If 726 727 mAnalysis.IssuesCountArray(CID_FIELDS) = _ 728 mAnalysis.IssuesCountArray(CID_FIELDS) + 1 729 End With 730 mAnalysis.Issues.Add myIssue 731 Set myIssue = Nothing 732 End If 733 Exit Sub 734 735HandleErrors: 736 WriteDebug currentFunctionName & " : " & mAnalysis.name & ": " & Err.Number & " " & Err.Description & " " & Err.Source 737End Sub 738 739'Get field DS Info 740Sub Analyze_MailMerge_DataSource(currDoc As Document) 741 On Error GoTo HandleErrors 742 Dim currentFunctionName As String 743 currentFunctionName = "Analyze_MailMerge_DataSource" 744 ' There may be no mail merge in the document 745 If (currDoc.MailMerge.DataSource.Type = wdNoMergeInfo) Then 746 Exit Sub 747 End If 748 749 'Dim issue As SimpleAnalysisInfo 750 If (currDoc.MailMerge.DataSource.Type <> wdNoMergeInfo) Then 751 Dim myIssue As IssueInfo 752 Set myIssue = New IssueInfo 753 With myIssue 754 .IssueID = CID_CONTENT_AND_DOCUMENT_PROPERTIES 755 .IssueType = RID_STR_COMMON_ISSUE_CONTENT_AND_DOCUMENT_PROPERTIES 756 .SubType = RID_STR_WORD_SUBISSUE_MAILMERGE_DATASOURCE 757 .Location = .CLocationDocument 758 759 .IssueTypeXML = CSTR_ISSUE_CONTENT_DOCUMENT_PROPERTIES 760 .SubTypeXML = CSTR_SUBISSUE_MAILMERGE_DATASOURCE 761 .locationXML = .CXMLLocationDocument 762 763 .Attributes.Add RID_STR_COMMON_ATTRIBUTE_NAME 764 .Values.Add currDoc.MailMerge.DataSource.name 765 .Attributes.Add RID_STR_WORD_ATTRIBUTE_DATASOURCE 766 .Values.Add currDoc.MailMerge.DataSource.Type 767 768 mAnalysis.IssuesCountArray(CID_CONTENT_AND_DOCUMENT_PROPERTIES) = _ 769 mAnalysis.IssuesCountArray(CID_CONTENT_AND_DOCUMENT_PROPERTIES) + 1 770 End With 771 772 mAnalysis.Issues.Add myIssue 773 Set myIssue = Nothing 774 End If 775 Exit Sub 776 777HandleErrors: 778 WriteDebug currentFunctionName & " : " & mAnalysis.name & ": " & Err.Number & " " & Err.Description & " " & Err.Source 779End Sub 780 781Function getFormFieldTypeAsString(fieldType As WdFieldType) 782 Dim Str As String 783 784 Select Case fieldType 785 Case wdFieldFormCheckBox 786 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_CHECK_BOX 787 Case wdFieldFormDropDown 788 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_DROP_DOWN 789 Case wdFieldFormTextInput 790 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_TEXT 791 Case Else 792 Str = RID_STR_WORD_ENUMERATION_UNKNOWN 793 End Select 794 795 getFormFieldTypeAsString = Str 796End Function 797Function getTextFormFieldTypeAsString(fieldType As WdTextFormFieldType) 798 Dim Str As String 799 800 Select Case fieldType 801 Case wdCalculationText 802 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_CALCULATION 803 Case wdCurrentDateText 804 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_CURRENT_DATE 805 Case wdCurrentTimeText 806 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_CURRENT_TIME 807 Case wdDateText 808 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_DATE 809 Case wdNumberText 810 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_NUMBER 811 Case wdRegularText 812 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_REGULAR 813 Case Else 814 Str = RID_STR_WORD_ENUMERATION_UNKNOWN 815 End Select 816 817 getTextFormFieldTypeAsString = Str 818End Function 819Function getTextFormFieldDefaultAsString(fieldType As WdTextFormFieldType) 820 Dim Str As String 821 822 Select Case fieldType 823 Case wdCalculationText 824 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_DEFAULT_EXPRESSION 825 Case wdCurrentDateText 826 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_DEFAULT_DATE 827 Case wdCurrentTimeText 828 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_DEFAULT_TIME 829 Case wdDateText 830 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_DEFAULT_DATE 831 Case wdNumberText 832 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_DEFAULT_NUMBER 833 Case wdRegularText 834 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_DEFAULT_TEXT 835 Case Else 836 Str = RID_STR_WORD_ENUMERATION_UNKNOWN 837 End Select 838 839 getTextFormFieldDefaultAsString = Str 840End Function 841Function getTextFormFieldFormatAsString(fieldType As WdTextFormFieldType) 842 Dim Str As String 843 844 Select Case fieldType 845 Case wdCalculationText 846 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_FORMAT_NUMBER 847 Case wdCurrentDateText 848 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_FORMAT_DATE 849 Case wdCurrentTimeText 850 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_FORMAT_TIME 851 Case wdDateText 852 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_FORMAT_DATE 853 Case wdNumberText 854 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_FORMAT_NUMBER 855 Case wdRegularText 856 Str = RID_STR_WORD_ENUMERATION_FORM_FIELD_FORMAT_TEXT 857 Case Else 858 Str = RID_STR_WORD_ENUMERATION_UNKNOWN 859 End Select 860 861 getTextFormFieldFormatAsString = Str 862End Function 863 864Sub Analyze_FieldAndFormFieldIssues(currDoc As Document) 865 On Error GoTo HandleErrors 866 Dim currentFunctionName As String 867 currentFunctionName = "Analyze_FormFields" 868 Dim myIssue As IssueInfo 869 870 'Analysze all Fields in doc 871 Dim myField As Field 872 873 For Each myField In currDoc.Fields 874 'Analyze Mail Merge Fields 875 Analyze_MailMergeField myField 876 877 'Analyze TOA Fields 878 Analyze_TOAField myField 879 Next myField 880 881 'Analyze FormField doc issues 882 If currDoc.FormFields.count = 0 Then GoTo FinalExit 883 884 If (currDoc.FormFields.Shaded) Then 885 Set myIssue = New IssueInfo 886 With myIssue 887 .IssueID = CID_FIELDS 888 .IssueType = RID_STR_WORD_ISSUE_FIELDS 889 .SubType = RID_STR_WORD_SUBISSUE_APPEARANCE 890 .Location = .CLocationDocument 891 892 .IssueTypeXML = CSTR_ISSUE_FIELDS 893 .SubTypeXML = CSTR_SUBISSUE_APPEARANCE 894 .locationXML = .CXMLLocationDocument 895 896 .Attributes.Add RID_STR_WORD_ATTRIBUTE_FORM_FIELD_GREYED 897 .Values.Add RID_STR_WORD_TRUE 898 mAnalysis.IssuesCountArray(CID_FIELDS) = _ 899 mAnalysis.IssuesCountArray(CID_FIELDS) + 1 900 End With 901 mAnalysis.Issues.Add myIssue 902 Set myIssue = Nothing 903 End If 904 905 'Analyse all FormFields in doc 906 Dim myFormField As FormField 907 908 For Each myFormField In currDoc.FormFields 909 Analyze_FormFieldIssue myFormField 910 Next myFormField 911 912FinalExit: 913 Set myIssue = Nothing 914 Set myFormField = Nothing 915 Exit Sub 916 917HandleErrors: 918 919 WriteDebug currentFunctionName & " : " & mAnalysis.name & ": " & Err.Number & " " & Err.Description & " " & Err.Source 920 Resume FinalExit 921End Sub 922 923Sub Analyze_FormFieldIssue(myFormField As FormField) 924 On Error GoTo HandleErrors 925 Dim currentFunctionName As String 926 currentFunctionName = "Analyze_FormFieldIssue" 927 Dim myIssue As IssueInfo 928 Dim bCheckBoxIssues As Boolean 929 Dim bFormFieldIssues As Boolean 930 931 bCheckBoxIssues = False 932 If (myFormField.Type = wdFieldFormCheckBox) Then 933 If myFormField.CheckBox.AutoSize Then 934 bCheckBoxIssues = True 935 End If 936 End If 937 938 bFormFieldIssues = bCheckBoxIssues 939 940 If Not bFormFieldIssues Then GoTo FinalExit 941 942 myFormField.Select 943 Set myIssue = New IssueInfo 944 With myIssue 945 .IssueID = CID_FIELDS 946 .IssueType = RID_STR_WORD_ISSUE_FIELDS 947 .SubType = RID_STR_WORD_SUBISSUE_FORM_FIELD 948 .Location = .CLocationPage 949 950 .IssueTypeXML = CSTR_ISSUE_FIELDS 951 .SubTypeXML = CSTR_SUBISSUE_FORM_FIELD 952 .locationXML = .CXMLLocationPage 953 954 .SubLocation = Selection.Information(wdActiveEndPageNumber) 955 .Line = Selection.Information(wdFirstCharacterLineNumber) 956 .column = Selection.Information(wdFirstCharacterColumnNumber) 957 myIssue.Attributes.Add RID_STR_COMMON_ATTRIBUTE_TYPE 958 myIssue.Values.Add getFormFieldTypeAsString(myFormField.Type) 959 End With 960 961 'Checkbox Issues 962 If (myFormField.Type = wdFieldFormCheckBox) Then 963 'AutoSize CheckBoxes 964 If myFormField.CheckBox.AutoSize Then 965 myIssue.Attributes.Add RID_STR_WORD_ATTRIBUTE_FORM_FIELD_AUTOSIZE 966 myIssue.Values.Add RID_STR_WORD_TRUE 967 End If 968 End If 969 970 'TextInput Issues 971 If myFormField.Type = wdFieldFormTextInput Then 972 myIssue.Attributes.Add RID_STR_WORD_ATTRIBUTE_FORM_FIELD_TEXT_FORM_FIELD_TYPE 973 myIssue.Values.Add getTextFormFieldTypeAsString(myFormField.TextInput.Type) 974 Dim bLostType As Boolean 975 bLostType = False 976 If (myFormField.TextInput.Type = wdCalculationText) Or _ 977 (myFormField.TextInput.Type = wdCurrentDateText) Or _ 978 (myFormField.TextInput.Type = wdCurrentTimeText) Then 979 AddIssueDetailsNote myIssue, 0, getTextFormFieldTypeAsString(myFormField.TextInput.Type) & _ 980 " " & RID_STR_WORD_NOTE_FORM_FIELD_TYPE_LOST 981 bLostType = True 982 End If 983 984 If (myFormField.TextInput.Format <> "") Then 985 myIssue.Attributes.Add getTextFormFieldFormatAsString(myFormField.TextInput.Type) 986 myIssue.Values.Add myFormField.TextInput.Format 987 End If 988 989 'Default text 990 If (myFormField.TextInput.Default <> "") Then 991 myIssue.Attributes.Add getTextFormFieldDefaultAsString(myFormField.TextInput.Type) 992 myIssue.Values.Add myFormField.TextInput.Default 993 End If 994 995 'Maximum text 996 If (myFormField.TextInput.Width <> 0) Then 997 myIssue.Attributes.Add RID_STR_WORD_ATTRIBUTE_FORM_FIELD_MAX_LENGTH 998 myIssue.Values.Add myFormField.TextInput.Width 999 End If 1000 1001 'Fill-in disabled 1002 If (myFormField.Enabled = False) And (Not bLostType) Then 1003 myIssue.Attributes.Add RID_STR_WORD_ATTRIBUTE_FORM_FIELD_FILLIN_ENABLED 1004 myIssue.Values.Add RID_STR_WORD_FALSE 1005 End If 1006 End If 1007 1008 'Help Key(F1) 1009 If (myFormField.OwnHelp And myFormField.HelpText <> "") Then 1010 myIssue.Attributes.Add RID_STR_WORD_ATTRIBUTE_FORM_FIELD_HELP_KEY_F1_OWN_TEXT 1011 myIssue.Values.Add myFormField.HelpText 1012 ElseIf ((Not myFormField.OwnHelp) And myFormField.HelpText <> "") Then 1013 myIssue.Attributes.Add RID_STR_WORD_ATTRIBUTE_FORM_FIELD_HELP_KEY_F1_AUTO_TEXT 1014 myIssue.Values.Add myFormField.HelpText 1015 End If 1016 1017 'StatusHelp 1018 If (myFormField.OwnStatus And myFormField.StatusText <> "") Then 1019 myIssue.Attributes.Add RID_STR_WORD_ATTRIBUTE_FORM_FIELD_STATUS_BAR_HELP_OWN_TEXT 1020 myIssue.Values.Add myFormField.StatusText 1021 ElseIf ((Not myFormField.OwnStatus) And myFormField.StatusText <> "") Then 1022 myIssue.Attributes.Add RID_STR_WORD_ATTRIBUTE_FORM_FIELD_STATUS_BAR_HELP_AUTO_TEXT 1023 myIssue.Values.Add myFormField.StatusText 1024 End If 1025 1026 'Macros 1027 If (myFormField.EntryMacro <> "") Then 1028 myIssue.Attributes.Add RID_STR_WORD_ATTRIBUTE_FORM_FIELD_ENTRY_MACRO 1029 myIssue.Values.Add myFormField.EntryMacro 1030 End If 1031 If (myFormField.ExitMacro <> "") Then 1032 myIssue.Attributes.Add RID_STR_WORD_ATTRIBUTE_FORM_FIELD_EXIT_MACRO 1033 myIssue.Values.Add myFormField.ExitMacro 1034 End If 1035 If (myFormField.EntryMacro <> "") Or (myFormField.ExitMacro <> "") Then 1036 mAnalysis.MacroNumFieldsUsingMacros = 1 + mAnalysis.MacroNumFieldsUsingMacros 1037 End If 1038 1039 'LockedField 1040 If (myFormField.Enabled = False) And (myFormField.Type <> wdFieldFormTextInput) Then 1041 myIssue.Attributes.Add RID_STR_WORD_ATTRIBUTE_FORM_FIELD_LOCKED 1042 myIssue.Values.Add RID_STR_WORD_TRUE 1043 End If 1044 1045 mAnalysis.IssuesCountArray(CID_FIELDS) = _ 1046 mAnalysis.IssuesCountArray(CID_FIELDS) + 1 1047 1048 mAnalysis.Issues.Add myIssue 1049 1050FinalExit: 1051 Set myIssue = Nothing 1052 Exit Sub 1053 1054HandleErrors: 1055 'Log first occurrence for this doc 1056 If Not mbFormFieldErrorLogged Then 1057 WriteDebug currentFunctionName & " : " & mAnalysis.name & ": " & Err.Number & " " & Err.Description & " " & Err.Source 1058 mbFormFieldErrorLogged = True 1059 End If 1060 Resume FinalExit 1061End Sub 1062 1063 1064Sub Analyze_TOA(currDoc As Document) 1065 On Error GoTo HandleErrors 1066 Dim currentFunctionName As String 1067 currentFunctionName = "Analyze_TOA" 1068 1069 Dim toa As TableOfAuthorities 1070 Dim myIssue As IssueInfo 1071 Dim myRng As Range 1072 1073 For Each toa In currDoc.TablesOfAuthorities 1074 Set myRng = toa.Range 1075 myRng.start = myRng.End 1076 Set myIssue = New IssueInfo 1077 myRng.Select 1078 1079 Dim TabLeaderAsString As String 1080 Select Case toa.TabLeader 1081 Case wdTabLeaderDashes 1082 TabLeaderAsString = RID_STR_WORD_ENUMERATION_INDEX_LEADER_DASHES 1083 Case wdTabLeaderDots 1084 TabLeaderAsString = RID_STR_WORD_ENUMERATION_INDEX_LEADER_DOTS 1085 Case wdTabLeaderHeavy 1086 TabLeaderAsString = RID_STR_WORD_ENUMERATION_INDEX_LEADER_HEAVY 1087 Case wdTabLeaderLines 1088 TabLeaderAsString = RID_STR_WORD_ENUMERATION_INDEX_LEADER_LINES 1089 Case wdTabLeaderMiddleDot 1090 TabLeaderAsString = RID_STR_WORD_ENUMERATION_INDEX_LEADER_MIDDLEDOT 1091 Case wdTabLeaderSpaces 1092 TabLeaderAsString = RID_STR_WORD_ENUMERATION_INDEX_LEADER_SPACES 1093 Case Else 1094 TabLeaderAsString = RID_STR_WORD_ENUMERATION_UNKNOWN 1095 End Select 1096 1097 Dim FormatAsString As String 1098 Select Case currDoc.TablesOfAuthorities.Format 1099 Case wdTOAClassic 1100 FormatAsString = RID_STR_WORD_ENUMERATION_INDEX_TABLES_CLASSIC 1101 Case wdTOADistinctive 1102 FormatAsString = RID_STR_WORD_ENUMERATION_INDEX_TABLES_DISTINCTIVE 1103 Case wdTOAFormal 1104 FormatAsString = RID_STR_WORD_ENUMERATION_INDEX_TABLES_FORMAL 1105 Case wdTOASimple 1106 FormatAsString = RID_STR_WORD_ENUMERATION_INDEX_TABLES_SIMPLE 1107 Case wdTOATemplate 1108 FormatAsString = RID_STR_WORD_ENUMERATION_INDEX_TABLES_FROM_TEMPLATE 1109 Case Else 1110 FormatAsString = RID_STR_WORD_ENUMERATION_UNKNOWN 1111 End Select 1112 1113 With myIssue 1114 .IssueID = CID_INDEX_AND_REFERENCES 1115 .IssueType = RID_STR_WORD_ISSUE_INDEX_AND_REFERENCES 1116 .SubType = RID_STR_WORD_SUBISSUE_TABLE_OF_AUTHORITIES 1117 .Location = .CLocationPage 1118 1119 .IssueTypeXML = CSTR_ISSUE_INDEX_AND_REFERENCES 1120 .SubTypeXML = CSTR_SUBISSUE_TABLE_OF_AUTHORITIES 1121 .locationXML = .CXMLLocationPage 1122 1123 .SubLocation = myRng.Information(wdActiveEndPageNumber) 1124 .Attributes.Add RID_STR_WORD_ATTRIBUTE_LEADER 1125 .Values.Add TabLeaderAsString 1126 1127 AddIssueDetailsNote myIssue, 0, RID_STR_WORD_NOTE_TOA_MIGRATE_AS_PLAIN_TEXT 1128 1129 mAnalysis.IssuesCountArray(CID_INDEX_AND_REFERENCES) = _ 1130 mAnalysis.IssuesCountArray(CID_INDEX_AND_REFERENCES) + 1 1131 End With 1132 1133 mAnalysis.Issues.Add myIssue 1134 Set myIssue = Nothing 1135 Set myRng = Nothing 1136 Next 1137FinalExit: 1138 Set myIssue = Nothing 1139 Set myRng = Nothing 1140 Exit Sub 1141 1142HandleErrors: 1143 WriteDebug currentFunctionName & " : " & mAnalysis.name & ": " & Err.Number & " " & Err.Description & " " & Err.Source 1144 Resume FinalExit 1145End Sub 1146 1147Sub Analyze_TOAField(myField As Field) 1148 On Error GoTo HandleErrors 1149 Dim currentFunctionName As String 1150 currentFunctionName = "Analyze_TOAField" 1151 1152 Dim toa As TableOfAuthorities 1153 Dim myIssue As IssueInfo 1154 1155 If myField.Type = wdFieldTOAEntry Then 1156 Set myIssue = New IssueInfo 1157 myField.Select 1158 1159 With myIssue 1160 .IssueID = CID_FIELDS 1161 .IssueType = RID_STR_WORD_ISSUE_FIELDS 1162 .SubType = RID_STR_WORD_SUBISSUE_TABLE_OF_AUTHORITIES_FIELD 1163 .Location = .CLocationPage 1164 1165 .IssueTypeXML = CSTR_ISSUE_FIELDS 1166 .SubTypeXML = CSTR_SUBISSUE_TABLE_OF_AUTHORITIES_FIELD 1167 .locationXML = .CXMLLocationPage 1168 1169 .SubLocation = Selection.Information(wdActiveEndPageNumber) 1170 .Line = Selection.Information(wdFirstCharacterLineNumber) 1171 .column = Selection.Information(wdFirstCharacterColumnNumber) 1172 1173 .Attributes.Add RID_STR_WORD_ATTRIBUTE_FIELD_TEXT 1174 .Values.Add myField.Code.Text 1175 1176 AddIssueDetailsNote myIssue, 0, RID_STR_WORD_NOTE_TOA_FIELD_LOST_ON_ROUNDTRIP 1177 1178 mAnalysis.IssuesCountArray(CID_FIELDS) = _ 1179 mAnalysis.IssuesCountArray(CID_FIELDS) + 1 1180 End With 1181 1182 mAnalysis.Issues.Add myIssue 1183 Set myIssue = Nothing 1184 End If 1185 1186FinalExit: 1187 Set myIssue = Nothing 1188 Exit Sub 1189 1190HandleErrors: 1191 WriteDebug currentFunctionName & " : " & mAnalysis.name & ": " & Err.Number & " " & Err.Description & " " & Err.Source 1192 Resume FinalExit 1193End Sub 1194 1195Sub Analyze_Tables_Borders(currDoc As Document) 1196 On Error GoTo HandleErrors 1197 Dim currentFunctionName As String 1198 currentFunctionName = "Analyze_Tables_Borders" 1199 Dim myIssue As IssueInfo 1200 Set myIssue = New IssueInfo 1201 Dim aTable As Table 1202 Dim invalidBorders As String 1203 1204 For Each aTable In currDoc.Tables 1205 invalidBorders = GetInvalidBorder(aTable) 1206 If invalidBorders <> "" Then 1207 aTable.Range.Select 1208 Set myIssue = New IssueInfo 1209 With myIssue 1210 .IssueID = CID_TABLES 1211 .IssueType = RID_STR_WORD_ISSUE_TABLES 1212 .SubType = RID_STR_WORD_SUBISSUE_BORDER_STYLES 1213 .Location = .CLocationPage 1214 1215 .IssueTypeXML = CSTR_ISSUE_TABLES 1216 .SubTypeXML = CSTR_SUBISSUE_BORDER_STYLES 1217 .locationXML = .CXMLLocationPage 1218 1219 .SubLocation = Selection.Information(wdActiveEndPageNumber) 1220 .Line = Selection.Information(wdFirstCharacterLineNumber) 1221 .column = Selection.Information(wdFirstCharacterColumnNumber) 1222 1223 .Attributes.Add RID_STR_WORD_ATTRIBUTE_BORDERS_NOT_DISPLAYING 1224 .Values.Add invalidBorders 1225 1226 AddIssueDetailsNote myIssue, 0, RID_STR_WORD_NOTE_TABLE_BORDER 1227 1228 mAnalysis.IssuesCountArray(CID_TABLES) = mAnalysis.IssuesCountArray(CID_TABLES) + 1 1229 End With 1230 1231 mAnalysis.Issues.Add myIssue 1232 Set myIssue = Nothing 1233 End If 1234 Next aTable 1235FinalExit: 1236 Set myIssue = Nothing 1237 Exit Sub 1238 1239HandleErrors: 1240 WriteDebug currentFunctionName & " : " & mAnalysis.name & ": " & Err.Number & " " & Err.Description & " " & Err.Source 1241 Resume FinalExit 1242End Sub 1243Function GetInvalidBorder(aTable As Table) As String 1244 1245 Dim theResult As String 1246 theResult = "" 1247 1248 If IsInvalidBorderStyle(aTable.Borders(wdBorderTop).LineStyle) Then 1249 theResult = theResult + "Top, " 1250 End If 1251 If IsInvalidBorderStyle(aTable.Borders(wdBorderBottom).LineStyle) Then 1252 theResult = theResult + "Bottom, " 1253 End If 1254 If IsInvalidBorderStyle(aTable.Borders(wdBorderDiagonalDown).LineStyle) Then 1255 theResult = theResult + "Down Diagonal, " 1256 End If 1257 If IsInvalidBorderStyle(aTable.Borders(wdBorderDiagonalUp).LineStyle) Then 1258 theResult = theResult + "Up Diagonal, " 1259 1260 End If 1261 If IsInvalidBorderStyle(aTable.Borders(wdBorderHorizontal).LineStyle) Then 1262 theResult = theResult + "Horizontal, " 1263 End If 1264 If IsInvalidBorderStyle(aTable.Borders(wdBorderLeft).LineStyle) Then 1265 theResult = theResult + "Left, " 1266 End If 1267 If IsInvalidBorderStyle(aTable.Borders(wdBorderRight).LineStyle) Then 1268 theResult = theResult + "Right, " 1269 End If 1270 If IsInvalidBorderStyle(aTable.Borders(wdBorderVertical).LineStyle) Then 1271 theResult = theResult + "Vertical, " 1272 End If 1273 1274 If theResult <> "" Then 1275 theResult = Left(theResult, (Len(theResult) - 2)) + "." 1276 End If 1277 1278 GetInvalidBorder = theResult 1279End Function 1280 1281Function IsInvalidBorderStyle(aStyle As WdLineStyle) As Boolean 1282 1283 Dim IsInvalid As Boolean 1284 1285 Select Case aStyle 1286 Case wdLineStyleDot, wdLineStyleDashSmallGap, wdLineStyleDashLargeGap, wdLineStyleDashDot, _ 1287 wdLineStyleDashDotDot, wdLineStyleTriple, wdLineStyleThinThickThinSmallGap, wdLineStyleThinThickMedGap, _ 1288 wdLineStyleThickThinMedGap, wdLineStyleThinThickThinMedGap, wdLineStyleThinThickLargeGap, _ 1289 wdLineStyleThickThinLargeGap, wdLineStyleThinThickThinLargeGap, wdLineStyleSingleWavy, _ 1290 wdLineStyleDoubleWavy, wdLineStyleDashDotStroked, wdLineStyleEmboss3D, wdLineStyleEngrave3D 1291 IsInvalid = True 1292 Case Else 1293 IsInvalid = False 1294 End Select 1295 1296 IsInvalidBorderStyle = IsInvalid 1297 1298End Function 1299 1300Private Sub Class_Initialize() 1301 Set mAnalysis = New DocumentAnalysis 1302End Sub 1303Private Sub Class_Terminate() 1304 Set mAnalysis = Nothing 1305End Sub 1306 1307Public Property Get Results() As DocumentAnalysis 1308 Set Results = mAnalysis 1309End Property 1310 1311Sub Analyze_NumberingTabs(currDoc As Document, docAnalysis As DocumentAnalysis) 1312 On Error GoTo HandleErrors 1313 Dim currentFunctionName As String 1314 currentFunctionName = "Analyze_NumberingTabs" 1315 1316 Dim tb As TabStop 1317 Dim customTabPos As Single 1318 Dim tabs As Integer 1319 Dim listLvl As Long 1320 Dim tp As Single 1321 Dim bHasAlignmentProblem As Boolean 1322 Dim bHasTooManyTabs As Boolean 1323 Dim myIssue As IssueInfo 1324 Dim p As Object 1325 1326 bHasAlignmentProblem = False 1327 bHasTooManyTabs = False 1328 1329 For Each p In currDoc.ListParagraphs 1330 tabs = 0 1331 For Each tb In p.TabStops 1332 If tb.customTab Then 1333 tabs = tabs + 1 1334 customTabPos = tb.Position 1335 End If 1336 Next 1337 1338 If tabs = 1 Then 1339 listLvl = p.Range.ListFormat.ListLevelNumber 1340 tp = p.Range.ListFormat.ListTemplate.ListLevels.item(listLvl).TabPosition 1341 If (p.Range.ListFormat.ListTemplate.ListLevels.item(listLvl).Alignment <> _ 1342 wdListLevelAlignLeft) Then 1343 ' ERROR: alignment problem 1344 bHasAlignmentProblem = True 1345 End If 1346 1347 If tp <> customTabPos Then 1348 p.Range.InsertBefore ("XXXXX") 1349 End If 1350 'OK - at least heuristically 1351 Else 1352 'ERROR: too many tabs 1353 bHasTooManyTabs = True 1354 End If 1355 Next 1356 1357 If (bHasAlignmentProblem) Then 1358 Set myIssue = New IssueInfo 1359 1360 With myIssue 1361 .IssueID = CID_INDEX_AND_REFERENCES 1362 .IssueType = RID_STR_WORD_ISSUE_INDEX_AND_REFERENCES 1363 .SubType = RID_STR_WORD_SUBISSUE_NUMBERING_TAB_ALIGNMENT 1364 .Location = .CLocationDocument 'Location string 1365 1366 .IssueTypeXML = CSTR_ISSUE_INDEX_AND_REFERENCES 1367 .SubTypeXML = CSTR_SUBISSUE_NUMBERING_TAB_ALIGNMENT 1368 .locationXML = .CXMLLocationDocument 1369 1370 AddIssueDetailsNote myIssue, 0, RID_STR_WORD_NOTE_NUMBERING_TAB_ALIGNMENT 1371 1372 docAnalysis.IssuesCountArray(CID_INDEX_AND_REFERENCES) = _ 1373 docAnalysis.IssuesCountArray(CID_INDEX_AND_REFERENCES) + 1 1374 End With 1375 docAnalysis.Issues.Add myIssue 1376 Set myIssue = Nothing 1377 End If 1378 1379 If (bHasTooManyTabs) Then 1380 Set myIssue = New IssueInfo 1381 1382 With myIssue 1383 .IssueID = CID_INDEX_AND_REFERENCES 1384 .IssueType = RID_STR_WORD_ISSUE_INDEX_AND_REFERENCES 1385 .SubType = RID_STR_WORD_SUBISSUE_NUMBERING_TAB_OVERFLOW 1386 .Location = .CLocationDocument 'Location string 1387 1388 .IssueTypeXML = CSTR_ISSUE_INDEX_AND_REFERENCES 1389 .SubTypeXML = CSTR_SUBISSUE_NUMBERING_TAB_OVERFLOW 1390 .locationXML = .CXMLLocationDocument 1391 1392 AddIssueDetailsNote myIssue, 0, RID_STR_WORD_NOTE_NUMBERING_TAB_OVERFLOW 1393 1394 docAnalysis.IssuesCountArray(CID_INDEX_AND_REFERENCES) = _ 1395 docAnalysis.IssuesCountArray(CID_INDEX_AND_REFERENCES) + 1 1396 End With 1397 docAnalysis.Issues.Add myIssue 1398 Set myIssue = Nothing 1399 End If 1400 1401FinalExit: 1402 Exit Sub 1403 1404HandleErrors: 1405 WriteDebug currentFunctionName & " : " & mAnalysis.name & ": " & Err.Number & " " & Err.Description & " " & Err.Source 1406 Set myIssue = Nothing 1407 Resume FinalExit 1408End Sub 1409 1410Sub Analyze_Numbering(currDoc As Document, docAnalysis As DocumentAnalysis) 1411 On Error GoTo HandleErrors 1412 Dim currentFunctionName As String 1413 currentFunctionName = "Analyze_Numbering" 1414 1415 Dim myIssue As IssueInfo 1416 Dim nFormatProblems As Integer 1417 Dim nAlignmentProblems As Integer 1418 nFormatProblems = 0 1419 nAlignmentProblems = 0 1420 1421 Dim lt As ListTemplate 1422 Dim lvl As ListLevel 1423 Dim I, l_, p1, p2, v1, v2 As Integer 1424 Dim display_levels As Integer 1425 Dim fmt, prefix, postfix, res As String 1426 1427 For Each lt In currDoc.ListTemplates 1428 l_ = 0 1429 For Each lvl In lt.ListLevels 1430 l_ = l_ + 1 1431 'Selection.TypeText Text:="List Number Format " + lvl.NumberFormat 1432 'Apply Heuristic 1433 fmt = lvl.NumberFormat 1434 p1 = InStr(fmt, "%") 1435 p2 = InStrRev(fmt, "%") 1436 v1 = val(Mid(fmt, p1 + 1, 1)) 1437 v2 = val(Mid(fmt, p2 + 1, 1)) 1438 display_levels = v2 - v1 + 1 1439 prefix = Mid(fmt, 1, p1 - 1) 1440 postfix = Mid(fmt, p2 + 2) 1441 'Check Heuristic 1442 res = prefix 1443 For I = 2 To display_levels 1444 res = "%" + Trim(Str(l_ - I + 1)) + "." + res 1445 Next 1446 res = res + "%" + Trim(Str(l_)) + postfix 1447 If (StrComp(res, fmt) <> 0) Then 1448 nFormatProblems = nFormatProblems + 1 1449 'Selection.TypeText Text:="Label Problem: NumberFormat=" + fmt + " Heuristic=" + res 1450 End If 1451 1452 'check alignment 1453 If (lvl.NumberPosition <> wdListLevelAlignLeft) Then 1454 nAlignmentProblems = nAlignmentProblems + 1 1455 'Selection.TypeText Text:="Number alignment problem" 1456 End If 1457 Next 1458 Next 1459 1460 If (nFormatProblems > 0) Then 1461 Set myIssue = New IssueInfo 1462 1463 With myIssue 1464 .IssueID = CID_INDEX_AND_REFERENCES 1465 .IssueType = RID_STR_WORD_ISSUE_INDEX_AND_REFERENCES 1466 .SubType = RID_STR_WORD_SUBISSUE_NUMBERING_FORMAT 1467 .Location = .CLocationDocument 'Location string 1468 1469 .IssueTypeXML = CSTR_ISSUE_INDEX_AND_REFERENCES 1470 .SubTypeXML = CSTR_SUBISSUE_NUMBERING_FORMAT 1471 .locationXML = .CXMLLocationDocument 1472 1473 .Attributes.Add RID_STR_WORD_ATTRIBUTE_COUNT 1474 .Values.Add nFormatProblems 1475 1476 AddIssueDetailsNote myIssue, 0, RID_STR_WORD_NOTE_NUMBERING_FORMAT 1477 1478 docAnalysis.IssuesCountArray(CID_INDEX_AND_REFERENCES) = _ 1479 docAnalysis.IssuesCountArray(CID_INDEX_AND_REFERENCES) + 1 1480 End With 1481 docAnalysis.Issues.Add myIssue 1482 Set myIssue = Nothing 1483 End If 1484 1485 If (nAlignmentProblems > 0) Then 1486 Set myIssue = New IssueInfo 1487 1488 With myIssue 1489 .IssueID = CID_INDEX_AND_REFERENCES 1490 .IssueType = RID_STR_WORD_ISSUE_INDEX_AND_REFERENCES 1491 .SubType = RID_STR_WORD_SUBISSUE_NUMBERING_ALIGNMENT 1492 .Location = .CLocationDocument 'Location string 1493 1494 .IssueTypeXML = CSTR_ISSUE_INDEX_AND_REFERENCES 1495 .SubTypeXML = CSTR_SUBISSUE_NUMBERING_ALIGNMENT 1496 .locationXML = .CXMLLocationDocument 1497 1498 .Attributes.Add RID_STR_WORD_ATTRIBUTE_COUNT 1499 .Values.Add nAlignmentProblems 1500 1501 AddIssueDetailsNote myIssue, 0, RID_STR_WORD_NOTE_NUMBERING_ALIGNMENT 1502 1503 docAnalysis.IssuesCountArray(CID_INDEX_AND_REFERENCES) = _ 1504 docAnalysis.IssuesCountArray(CID_INDEX_AND_REFERENCES) + 1 1505 End With 1506 docAnalysis.Issues.Add myIssue 1507 Set myIssue = Nothing 1508 End If 1509 1510FinalExit: 1511 Exit Sub 1512 1513HandleErrors: 1514 WriteDebug currentFunctionName & " : " & mAnalysis.name & ": " & Err.Number & " " & Err.Description & " " & Err.Source 1515 Set myIssue = Nothing 1516 Resume FinalExit 1517End Sub 1518 1519