VBA crashes when trying to insert a multitude of CrossReferences - vba

I encountered a mysterious problem when trying to run the following thing in VBA for Word:
Option Explicit
Sub Test()
Dim allHeadlines As Variant
Dim i As Integer
allHeadlines = ActiveDocument.GetCrossReferenceItems(wdRefTypeHeading) ' Gets all headlines
For i = 1 To UBound(allHeadlines)
Selection.InsertCrossReference ReferenceType:="Nummeriertes Element", _
ReferenceKind:=wdNumberRelativeContext, ReferenceItem:=Str(i), _
InsertAsHyperlink:=True, IncludePosition:=False, SeparateNumbers:=False, _
SeparatorString:=" "
Next
End Sub
The idea was simple: Just get all headlines and write them down automatically. (Actually, my intention was a bit different, but I broke the program down as much as I could.) "Nummeriertes Element" means "numbered element".
After 296 elements, the program crashes with a very unspecific error (Runtime Error '4198': "Command Failed") at the Selection.InsertCrossReference command. If I ignore the error and try to move on, Word crashes with an equally unspecific "heap damaged" error.
What also bothers me is that if I restart the Sub, it will fail immediately with Runtime Error '4198'. I have to restart Word completely to be able to run the Sub again, and then it will again crash at the same point (296 elements). Seems like some buffer is full and will not be cleared until I restart Word, but this is very annoying (I have much more than 300 headlines in this document).
I am quite at a loss here, because I do not really understand what is going on, or how to circumvent the problem. Does somebody else have an idea what is going on or what I am doing wrong?

The reason you are getting the error is you don't have a "Nummeriertes Element" reference in your document perhaps OR, more likely, you have 295 "Nummeriertes Element" in your document. When it tries to insert the reference to "Nummeriertes Element"(296), it bombs. The bombing after slamming through a couple pretty fast may just be an issue with Word (I've seen some pretty strange things happen with word and .docm corruptions). Unfortunately, you get that awful error which means absolutely nothing.
Option Explicit
Sub Test()
Dim allHeadlines As Variant
Dim doc As Document
Dim i As Integer
allHeadlines = ActiveDocument.GetCrossReferenceItems(wdRefTypeHeading) ' Gets all headlines
For i = 1 To UBound(allHeadlines)
Selection.InsertCrossReference ReferenceType:=wdRefTypeHeading, _
ReferenceKind:=wdNumberRelativeContext, ReferenceItem:=i, _
InsertAsHyperlink:=True, IncludePosition:=False, SeparateNumbers:=False, _
SeparatorString:=" "
Next i
End Sub
This will cross reference to your headings. When you specify that your ReferenceType is "Nummeriertes Element" on the backend (I assume), it is doing a GetCrossReferenceItems(wdRefTypeNumberedItem) and then you specify you want to get it by the ordinal with wdNumberRelativeContext and trying to grab GetCrossReferenceItems(wdRefTypeNumberedItem)(296) which doesn't exist.
But when you change your ReferenceType to wdRefTypeHeading it will cross reference the heading itself at the ordinal and not your numbered list items. You can the drop then str(i) to just i
Hope it helps.

Related

Visio: DOS Sharing violation (Error 1532)

So I'm really confused right now. Out of the blue my code gets me the error "DOS Sharing violation".
It's weird because, it says that is trying to save my document, but I just want to open it.
This is my Code:
Public Sub ReadActivity()
Dim vsoDocument As Visio.Document
Dim vsoPage As Visio.Page
Set vsoDocument = Documents.Open("C:\Users\Philip\Dropbox\Test\Aktivität0.vsdx")
Set vsoPage = vsoDocument.Pages(1)
SvgExport (ActiveDocument.path & "\files_and_images\" & Left(ActiveDocument.name, (InStrRev(ActiveDocument.name, ".", -1, vbTextCompare) - 1)) & ".svg")
CreateCodeActivity
vsoDocument.Close
End Sub
So as you might see the code is simple nothing special is going on.
Before calling the method I'm using this for encoding my textfile: VBA : save a file with UTF-8 without BOM
And two things are very weird. First of all, I used this method two days in a row for coding the method "CreateCodeActivity" and I didn't have any problems. And second, if I call the method let's say three times, on the third time everything works perfectly...
Where might be the problem?
Thank you #Shmukko for the tip, it is really the windows defender that gives me the error.
For Windows 10 the solution is: Go to Settings and select Update & security -> Windows Defender. Select Exclude a file extension and enter the file type for Visio.
That's it.

Access autocad object properties without opening it by VBA

I have been using folder browser for VBA, I could paste the code of it, but bottom line is that I get returned file name as a string.
Is there any way to access drawing properties (i.e number of layouts) without open?
Public Sub TestFileDialog()
dwgname = FileBrowseOpen("C:", "*", ".dwg", 1) 'dwgname is typeof string
End Sub
Its only the first step (use of FileBrowseOpen function is shown, but also i can use FolderBrowse and collect all .dwg inside of folder),actually i had in mind to batch export all layouts of selected .dwgs to currenty open one. Is there any chance for that?
To effectively read a .dwg file you'll need to open AutoCAD, otherwise the information is not accessible. Some properties may be, such as author, but not number of layouts...
But you can use AutoCAD Console (accoreconsole.exe) to run a headless AutoCAD and use APIs to read any information you need. This is really fast for reading lot's of files and the user will not see it running (but it needs to be installed anyway).
http://aucache.autodesk.com/au2012/sessionsFiles/3338/3323/handout_3338_CP3338-Handout.pdf
you could stay in VBA and use ObjectDBX
it leads to a very similar approach as accoreconsole.exe on in .NET does, i.e you won't see any drawing open in UI since it works on the database itself
It requires adding library reference (Tools->References) to "AutoCAD/ObjectDBX Common XX.Y Type Library", where "XX.Y" is "19.0" for AutoCAD 2014
a minimal functioning code is
Sub main()
Dim myAxDbDoc As AxDbDocument
Dim FullFileName As String
FullFileName = "C:\..\mydrawing.dwg" '<== put here the full name of the file to be opened
Set myAxDbDoc = AxDb_SetDrawing(FullFileName)
MsgBox myAxDbDoc.Layers.Count
End Sub
Function AxDb_SetDrawing(FullFileName As String) As AxDbDocument
Dim DBXDoc As AxDbDocument
Set DBXDoc = Application.GetInterfaceObject("ObjectDBX.AxDbDocument.19") '<== place correct AutoCAD version numeber ("19" works for AutoCAD 2014)
On Error Resume Next
DBXDoc.Open FullFileName
If Err <> 0 Then
MsgBox "Couldn't open" & vbCrLf & vbCrLf & FullFileName, vbOKOnly + vbCritical, "AxDB_SetDrawing"
Else
Set AxDb_SetDrawing = DBXDoc
End If
On Error GoTo 0
End Function
Still, you must have one AutoCAD session running from which make this sub run! But you should have it since talked about "currently open" drawing

ActiveWorkbook.Names.add seems to be incompatible with "Function"

I have a problem with :
Function Create_Model(adress As range, name As String) As String
Dim Msg As String
On Error GoTo ErrorHandler
ActiveWorkbook.Names.add "toto", "=Interface!$I$19"
Create_Model=name
Exit Function
ErrorHandler:
If Err.Number <> 0 Then
Msg = "Error # " & Str(Err.Number) & " was generated by " _
& Err.Source & Chr(13) & "Error Line: " & Erl & Chr(13) & Err.Description
MsgBox Msg, , "Error", Err.HelpFile, Err.HelpContext
End If
Resume Next
End Function
Indeed, if I run this, I get :
"Error # 1004 was generated by VBAProject
Error Line: 0
Application-defined or object-defined error"
It seems that the problem come from the use of "Function" because if I try to execute this with a "Sub", it's working.
Someone could please explain me why I can't do this with a "Function" and how I could replicate this function otherwise?
P.S : If I compile using Debug->Compile VBAProject. I don't get any message.
P.S.2 : This function aims to be used in excel formula.
P.S.3 : Argument used are : adress = J18:L20 and name = "Test". And finnaly, I would like replace "toto" by name and "=Interface!$I$19" by adress.
Thanks for your help.
After the comments below, I got to thinking, and realized that my original answer (see below) is perhaps more based in (my own!) best practice than being technically correct.
The main difference between a Function and a Subroutine is that a Function can return a value, while a Subroutine cannot.
I have heard of other issues in using Function rather than Subroutine but can't find a list right now. You have apparently found one, though! These (perhaps) rumors of issues, is why I tend to limit actions to Subroutines, and returning values to Functions.
After doing some digging, I've found the following resources that may help with further explanation of the difference between the two.
From Chip Pearson's site: a page called Macros and Functions
From ExcelFunctions.net: a page called Excel VBA Tutorial Part 4 - VBA Functions & Subroutines
Looks like I learned something today.
==ORIGINAL ANSWER==
Short answer and super high-level
Functions are typically not the best place to perform actions (on a worksheet, cell, file, create objects, etc). They are really good at returning values, and that is what they are designed for.
Subs or procedures are built for taking action.
I have never seen this particular issue, but have run into many things that trying to do them in a Function causes problems.

Method 'range' of object _global failed when doing nothing

I have a big macro which basically processes some columns and spits out results based on some cross-checking with an access 2003 database. It works absolutely fine - no hitches at all.
However, I recently had to make a modification to it. It was literally changing an '8' to a '9' in one line of the code. But next time I ran it, it threw the 1004: Method 'Range' of object '_Global' failed error. Excel 2003 is a funny thing - I once scratched my head for hours over this, trying to find offending lines of code that could be causing the error, but alas to no avail. I did something that I didn't expect to trigger anything:
Starting with the original macro (100% confirmed working), if I just open the code up, and then save it so the 'last updated' metadata will update to reflect the save, though absolutely nothing has changed, it will throw that error again on opening.
It's as if it's so fragile that saving the macro as is will break it. Any ideas?
Update: here's what I changed that initially brought about the issue
iOutputCols = 9 'this was changed to 9 from 8
ReDim Preserve sOutputCols(iOutputCols)
sOutputCols(0) = "Policy No"
sOutputCols(1) = "Client"
sOutputCols(2) = "Trans"
sOutputCols(3) = "Effective Date"
sOutputCols(4) = "ClosingRef"
sOutputCols(5) = "Gross"
sOutputCols(6) = "Comm"
sOutputCols(7) = "Net Due"
sOutputCols(8) = "Risk" 'this line was added
Making the change here, while originally causing the error, doesn't seem special - I did small changes like the above elsewhere in the code and in other modules, one time I even did something as testval = "test" and even that redundant line will produce the error. The most minimalistic way to cause it? Simply open it up, save it without changing anything, and on next use the error occurs.
The error occurs at this line, in a completely different code section which is part of a form:
If strErr <> "" Then MsgBox strErr, vbInformation + vbOKOnly, "Action Error"
Application.ScreenUpdating = True 'error occurs here, message box which shows me the error right above
End Sub
Update 2
Removing the error handling throws the error on this line
Case "> Send Next Period Reminder" 'error on line below
Call ReplaceText(wordApp, "[office_address]", Range("Address_" & Worksheets("UserParms").Range("F6").Value).Value) 'error this line
Call ReplaceText(wordApp, "[office_address2]", Range("Address2_" & Worksheets("UserParms").Range("F6").Value).Value)
'more of the same replacetexts below
For context, this is when an option is selected for "Send Next Period Reminder", which pulls a word .dot template from a static folder and populates it based on the data selected within the sheet (Hence the replace texts). This is in a different module and has never been touched before.
Try properly qualifying your Range method calls. You have lines like this:
Call ReplaceText(wordApp, "[office_address]", Range("Address_" & Worksheets("UserParms").Range("F6").Value).Value) 'error this line
Call ReplaceText(wordApp, "[office_address2]", Range("Address2_" & Worksheets("UserParms").Range("F6").Value).Value)
While it may not be obvious, there are cases, both environmental and code-based, where these unqualified uses of Range could fail. Change the references like Range("Address... to something like yourTargetWS.Range("Address...

What VBA code should be used in Microsoft Word 2007 Macro to create Table of Contents

I would like to define a macro in Microsoft Word 2007 that inserts a table of contents with the provided automatic styles when a hotkey is pressed. I successfully defined a macro to insert a non-styled (e.g. basic) table of contents as follows:
Sub InsertTableOfContents()
'
' InsertTableOfContents Macro
'
'
With ActiveDocument
.TablesOfContents.Add Range:=Selection.Range, RightAlignPageNumbers:= _
True, UseHeadingStyles:=True, UpperHeadingLevel:=1, _
LowerHeadingLevel:=3, IncludePageNumbers:=True, AddedStyles:="", _
UseHyperlinks:=True, HidePageNumbersInWeb:=True, UseOutlineLevels:= _
True
.TablesOfContents(1).TabLeader = wdTabLeaderDots
.TablesOfContents.Format = wdIndexIndent
End With
End Sub
However, when I attempt to insert a styled table of contents as follows:
Sub InsertStyledTOC()
'
' Macro to insert a table of contents styled like Automatic Table 2
'
ActiveDocument.AttachedTemplate.BuildingBlockEntries("Automatic Table 2"). _
Insert Where:=Selection.Range, RichText:=True
End Sub
I get the following error:
Run-time error 5941 The requested member of the collection does not exist
I beleive this indicates that the referenced member of BuildingBlockEntries (e.g. Automatic Table 2) does not exist, but I am unclear as to why or how to correct it.
Thank you for the help
Edit - I attempted to use the filepath to the application's default Building Blocks template as suggested:
Application.Templates("C:\Program Files\Microsoft Office\Office12\Document Parts\1033\Building Blocks.dotx").BuildingBlockEntries("Automatic Table 2").Insert Where:=Selection.Range _
, RichText:=True
However, I still receive the error: Run-time error 5941 The requested member of the collection does not exist
Your code expects the Building Blocks to be found in the attached template, which, if you haven't done anything special, is probably Normal.dotm. Microsoft actually stores built-in building blocks in a different template. If you record a macro, you'll see where this template is located (mine is in "C:\Users\owner\AppData\Roaming\Microsoft\Document Building Blocks\1033\14\Built-In Building Blocks.dotx").
So, you have two options. You can use the Templates collection to get to that template and insert the building block from there (macro recorder is your friend here). Or, you can save the building block to Normal.dotm to make accessing it a little easier. To do this, click on Insert > Quick Text > Buliding Blocks, find your Building Block in the list, edit its properties, and save it to Normal. If you do that, your code should work (I have 2010, but I'm betting this is pretty similar).
I don't know of any real difference between those two options, assuming this is just for you and not something you need to distribute.
Edited to add the code I get from the macro recorder:
Application.Templates( _
"C:\Users\owner\AppData\Roaming\Microsoft\Document Building Blocks\1033\14\Built-In Building Blocks.dotx" _
).BuildingBlockEntries("Automatic Table 2").Insert Where:=Selection.Range _
, RichText:=True
So, you should try replacing the code in InsertStyledTOC with that.