Update of multiple "link-fields" through VBA in word very slow - vba

I have a word file with approximately 750 fields which link to an Excel file (all to single cells, mostly not the same cell, always the same file), e.g.:
{ LINK Excel.SheetMacroEnabled.12 C:\\Dir1\\Dir1\\ExcelFile.xlsm Daten!Z1S1 \t \* MERGEFORMAT }
Updating the fields (CRTL+A -> F9) right after restarting Word is fairly quick. But if Word wasn't restarted it sometimes takes 10-20 minutes. On some PCs even restarting doesn't help.
When I checked the Task-Manger I saw multiple Excel-Instances could it be the Word open and closes the file for each field, even they all are linked to the same file. Is there a way to force Word to keep the file open?
I played around with the following VBA code with different variations, but so far I had no luck. This is the code I'm trying to get to work (going through all stories) and updating the fields:
Application.ScreenUpdating = False
ThisDocument.StoryRanges(i).Fields.Update
Selection.Fields.Update
I also tried to go through each field individually (which is undesirable since it means I have to build my own progress bar), but it doesn't resolve the performance issue:
Application.ScreenUpdating = False
ThisDocument.StoryRanges(i).Fields(j).Update
Selection.Fields.Update
DoEvents
Is there a way to prevent the low performance, or at least a way to further troubleshoot the problem?
Please Note: I also posted two other questions within this context:
VBA (Word): force user form to update in real time
How to show the progress of the “Fields.Update”-Method in VBA (Word)

Related

Mysterious Black Lines in Word When Using In-House VB.Net Application

A little backstory. I work at an organization that uses Mail Merge and SQL Databases to populate letters with names/addresses. Those letters are sent out to our donors as thank yous. These letters change frequently, and new ones come up at least 10 times a month.
To simplify our process, I created a program that allows you to copy/paste the letter body content into rich text boxes and when you press the 'Go' button, it opens a pre-made Word template and replaces bookmarks in the template with the copied body content.
The program works great with most letters, but some of them have a problem where these thick black lines are created and I'm unable to do ANYTHING to remove them. I can't right click them, I can't delete them with Backspace or Delete, and I can't highlight them.
I'm thinking that the problem may come from hidden formatting. Some of the employees that write the letters are using the Mac version of Office 2016, and I'm using Windows version. I sent an RTF file that showed the black lines for me to someone who uses the Mac version, and they said they couldn't see the lines.
My question is, is there a way to get rid of these lines or prevent them in the future? I've thought about upgrading Office version to 2019 on both ends, but there are quite a few people that have their hands in these letters and it may be difficult to upgrade everyone.
Please refer to the attached image for visual reference. Names and personal details have been removed.
EDIT: Here is the 'Go' code:
'create temp rtf files to maintain rtf
If strForm = "ANG2" Then
txtPreD.SaveFile("\\server\AcknowledgementLetters\fptemp.rtf")
txtPostD.SaveFile("\\server\AcknowledgementLetters\bptemp.rtf")
ElseIf strForm = "ANGL" Then
txtPreD.SaveFile("\\server\AcknowledgementLetters\predtemp.rtf")
txtPostD.SaveFile("\\server\AcknowledgementLetters\postdtemp.rtf")
txtBP.SaveFile("\\server\AcknowledgementLetters\bptemp.rtf")
Else
txtPreD.SaveFile("\\server\AcknowledgementLetters\predtemp.rtf")
txtPostD.SaveFile("\\server\AcknowledgementLetters\postdtemp.rtf")
End If
'if bookmarks exists, insert appropriate rtf files
If odoc.Bookmarks.Exists("fp") = True Then
goWord.ActiveDocument.Bookmarks("fp").Select()
goWord.Selection.InsertFile(FileName:="\\server\AcknowledgementLetters\fptemp.rtf")
End If
If odoc.Bookmarks.Exists("bp") = True Then
goWord.ActiveDocument.Bookmarks("bp").Select()
goWord.Selection.InsertFile(FileName:="\\server\AcknowledgementLetters\bptemp.rtf")
End If
If odoc.Bookmarks.Exists("PreD") = True Then
goWord.ActiveDocument.Bookmarks("PreD").Select()
goWord.Selection.InsertFile(FileName:="\\server\AcknowledgementLetters\predtemp.rtf")
End If
If odoc.Bookmarks.Exists("PostD") = True Then
goWord.ActiveDocument.Bookmarks("PostD").Select()
goWord.Selection.InsertFile(FileName:="\\server\AcknowledgementLetters\postdtemp.rtf")
End If
Before this happens, the program checks to see which template it needs to open and opens it as a Word object (odoc). This bit of code is really the only important part. After this, I just click Finish it just saves the file once I'm done checking it for errors. Also, yes, the RTF files that it creates DO have the black lines as well. Here is another picture of the program itself just so you can get a better idea of what's going on.

Excel Data Validations corrupt worksheets (when copying?)

Edit:
I further looked into this issue and have now a minimal file in which I can reproduce the error/bug. All Add-Ins are deactivated and I use only 4 lines of VBA-Code:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Tabelle15.Range(Target, Target.Offset(1, 0)).EntireRow.Copy
Target.Offset(2, 0).EntireRow.Insert
End Sub
The file has 2 sheets with formatting, data validations, outlines (3 levels) and some data on it.
What I do to corrupt the files:
Open the file
Click 3 times on Outline-Level 2 (--> hiding some rows)
Click 3 times on Outline-Level 3 (--> unhiding the rows)
Doubleclick on a cell to copy two rows via the VBA-Code
Close the file
Repeat until file is corrupt (sometimes it needs 10 or more loops, sometimes the file is corrupt after 1 loop)
The sheet in the file which gets corrupted doesn't have any code in it and is not activated in these loops. Here is a before and after of the corrupted data validation:
Before corruption:
<dataValidation type="list" allowBlank="1" showInputMessage="1" showErrorMessage="1" sqref="D11 D13 D15 D9">
After corruption:
<dataValidation type="list" allowBlank="1" showInputMessage="1" showErrorMessage="1" sqref="D11:A11 1:A90 A16384:D4294967295 D9">
I have still no idea why this happens. It would be interesting if anyone has the same issue or knows of a workaround so the corruption doesnt happen. (I tried the obvious Application.Screenupdating, Application.Wait,... )
End of Edit ---
Unfortunately I cannot say when this problem occurs, because I only get the resulting corrupt workbooks.
We have written a COM-AddIn for Excel in VB.net which does all sort of things (i.e. copying cells and sheets in specific structures, data connections to an SQL-DB, saving the workbook ...)
Now I get some workbooks from users of the AddIn which are corrupted. The problem is the users are working with the files and don't have a problem. Only after saving, closing and reopening the file Excel shows the question if the file should be repaired. Depending on the file type (we use *.xlsx and *.xlsb) Excel "repairs" the file and removes all formating from 1 sheet - in *.xlsb it doesn't repair and open at all.
After going through the xml-Sheet files I found that the corruption occurs in the dataValidation-Tags. Not in one specific data-validation sometimes in one sometimes in another.
The corrupted dataValidation-tags look like this:
<dataValidation type="list" allowBlank="1" showInputMessage="1" showErrorMessage="1" sqref="S26:26 1:A523 A16384:S4294967295 S32"><formula1>"Item1,Item2,Item3"</formula1></dataValidation>
Repairing the data validation or the files is not the problem. By now I can recover my workbooks just fine. My main problem is that I can't find any lead to where this problem comes from.
The most operations which happen on the sheets are copying and inserting (not pasting) of entire rows. On one sheet which gets corrupted sometimes, there is only "copying from" and no pasting or inserting on the sheet. It also seems that general performance of the file impacts the frequency of the problem occuring.
Since I can't give any code where this corruption occurs I don't expect to find a solution here, but perhaps someone had a similar problem and has a hint which shows me the right direction.
Additional infos: The problem occurs on different machines. I did not manage to reproduce the corruption process. As far as I know the problem only occured on Excel 2016 but I can't rule out that earlier versions corrupt the files just the same. I checked (at least on some machines) that all updates for Office and Windows are installed. The formulas in the data validations have (way) less than 255 characters. On the corrupted sheets there is no data connection to a database.
Any idea or hint is appreciated!

Sheet not found via codename

I'm running across and error that appears sporadically. Essentially, a master .xlsm file is used by multiple people to populate data for aggregation. I then use another .xlsm file with macros to pull the data and aggregate it into a single source file.
The code generally works quite well, with one exception:
'define range based on count'
Set rngItemRange = SourceWb.Sheets("Quality").Range(Cells(3, i), Cells((intItemCount + 2), i))
'write concatenated range'
targetwb.Sheets("Raw Data").Cells(pintDest_row, pintCol).Value = concatRange(rngItemRange)
It cannot find the tab "Quality" on some work books (but not all). Okay, maybe someone renamed the tab? checked that, thats not true. One thing that works as a work around: on the open source workbook, when debug throws an error, if i manually click the quality tab, then resume the macro, it will continue.
I also said, okay, well maybe there's some weird character recognition issue, so I started to refer to the sheet by the codename as shown in the vba editor. I experience the same behaviors.
This affects maybe 50% of the workbooks, and I cant find any root cause. I have similar code elsewhere, for different sheets, but this is the only one where i define a range to pass into a function using the "set" command. Again, this only happens sometimes on some workbooks, and i can continue to execute when i manually click on the tab i'm pulling data from.
I'll also add, there is only one workbook open with this sheet name, at any given time, so i dont think it's choking trying to figure which sheet is relevant. Plus sourceWb is a set variable.
Does someone have any clue whats going on? anything to try? solutions? help!
(Forgive any typos, I'm working on a broken thumb right now.)

Formatting issues duplicating table

Forward
I am making a "label program" that will print waybill information. Consists of a table in Word on a custom 3x5 inch document with 0 margins.
I currently have a simple form that, if you need copies, it will edit one of the cells so that each time it prints the "pieces count" is incremented. 1of10, 2of10, 3of10.....
While that worked the code submitted a separate print job for each "label". That created a problem for the end user where they would have to wait about 5-10 seconds between print jobs. When printing a couple of hundred of these at a time those seconds can add up.
Corrective solution
To try an alleviate this problem I wanted to make copies of the table so that 100 labels would be printed as one 100 page document. Found several solutions for copying pages of text but I have tables which complicated things. The closest solution I have found was:
With ActiveDocument
.Tables(1).Range.Copy
.Range.Select
'.Range.InsertAfter (Chr(11))
Selection.Collapse wdCollapseEnd
Selection.Paste
End With
And this does make a perfect copy of the table however it is merging the tables together. So if I wanted to loop this to create several more labels it would be doubling up the results every time since the code above just copies the first tabel.
To try and fix that issue I added a line break (vertical tab) before the paste. You will see that as the commented out line in the above snippet. This breaks up the tables but adds too much whitespace in between.
Page breaks seems like the solution here. While those did make the table break up they ended up creating a blank page in between each label which I was having enough of a time clearing from the GUI let alone in VBA.
The actual question
How can I take a table that is perfectly designed to fit on one 3x5 inch page and duplicate it X times. The caveat is I need to be able to find the cell programically that contains the pieces text. Currently I can use these absolute reference for the first table
ActiveDocument.Tables(1).Cell(5, 1).Range.Text
So if I had 3 tables for instance I need to be able to call each table and edit the text of the Cell(5, 1).
In case you ask
I know this functionality is better placed inside actual label programs like Bartender but those cost money that the company will not allocate for the only label my company uses.
The right concept was there. We needed to add a break in between the tables to disassociate them. Adding the vertical tab Chr(11) was obviously not the correct way to do it.
A proper section break would be the route to go here. Looking at MSDN you can see there are multiple types of section breaks. After testing a desirable outcome was acheived from using wdSectionBreakNextPage which is a "Section break on next page."
Basically just needed to add one line to the above code.
With ActiveDocument
.Tables(1).Range.Copy
.Range.Select
End With
With Selection
.Collapse wdCollapseEnd
.InsertBreak (wdSectionBreakNextPage)
.Paste
End With
I hate the use of Selection and I am going to look into that but for now this does function properly.
Since the tables are not single units we are able to query .Tables in order to edit each page individually.

Excel VBA: Resetting spreadsheet count

I have a excel VBA macro that dynamically generates and deletes spreadsheets based on user input. However, when I open the VBA IDE, it seems that although I am naming my spreadsheets in the subs that create/delete them, the overall count is still increasing.
For example, depending on how far into execution my program is, under the "Microsoft Excel Objects" folder in my current project, the spreadsheets in the current workbook could look something like
Sheet101(Sheet3)
Sheet103(Sheet2)
Sheet104(Sheet1)
Or
Sheet81(Inputs)
Sheet83(Date Adjustment Interpolation)
Sheet84(Pricing)
Sheet85(Comparison)
No matter if I delete the rest of them and add one, it still picks up where the last highest one left off.
I don't know how many times this macro will be run and I'd feel a lot better about putting it out there if I could reset this annoying tally on the number of spreadsheets that have ever been generated, since I don't know for sure where excel will cut me off. Plus it's just annoying.
My Question:
I would like to know how to alter that spreadsheet number, or at least what the relevant object is for doing so.
Thanks!
Thanks to #dijkay s suggestion on code names, I've found some code to accomplish this.
ThisWorkbook.VBProject.VBComponents("Sheet1").name = "test"
Will change the code name of Sheet1 to test, so in the Excel Objects folder, it will appear as test(Sheet1) for example.
This option, however, requires messing around with some trust/security settings in each individual excel client running the macro, which is unsuitable for my purposes, unfortunately. You can also change the value manually by changing the (Name) property directly in the IDE through the properties window.
here are some ideas you can try...
Sheets(x).Name = "Sheet" & x
or (assuming in this example, 'Sheet3' doesn't already exist:
Set Sheet3 = sheets.Add
Sheet3.name = "Sheet3"
This is more cleanup than re-setting
cheers,
Micéal