Slow performance setting Excel sheet print settings - vb.net

Using the Microsoft Office Interop libraries for Excel, I've written a routine in VB.Net that creates a large number of Excel worksheets, populates them and then formats them for printing. For every worksheet I call this small method to set the print settings:
Public Sub SetDefaultReportPrintSettings(orientation As ReportSheetOrientation, ws As Excel.Worksheet)
CType(ws.Parent, Excel.Workbook).Application.Windows(1).Zoom = 90
With ws.PageSetup
Select Case orientation
Case ReportSheetOrientation.Portrait : .Orientation = Excel.XlPageOrientation.xlPortrait
Case ReportSheetOrientation.Landscape : .Orientation = Excel.XlPageOrientation.xlLandscape
End Select
.Zoom = False
.FitToPagesTall = 1
.FitToPagesWide = 1
.LeftMargin = ws.Application.InchesToPoints(If(orientation = ReportSheetOrientation.Portrait, 0.75, 0.5))
.RightMargin = ws.Application.InchesToPoints(0.5)
.TopMargin = ws.Application.InchesToPoints(0.75)
.BottomMargin = ws.Application.InchesToPoints(0.75)
.CenterHorizontally = True
End With
End Sub
When I benchmark, this sub alone is apparently taking about 0.98 seconds. I don't understand why toggling a handful of settings would take that long. It might not seem like much, but when generating hundreds (or more) sheets this really adds to the routine time. The Excel application instance is hidden, so I don't think this is a screen updating issue.
Any way to make this go faster?

Chris Neilen's comment (set Application.PrintCommunication=False during PageSetup modifications) significantly improved my run time. According to documentation, Excel by default is actively communicating with the printer, which helps explain the slow performance.
I got an even bigger speed gain by setting Excel's view to Normal instead of Page Break Preview. This made a big difference, not in the PageSetup code, but for the rest of my Excel routines. The documentation again explains Excel does additional calculations for page breaks.
https://msdn.microsoft.com/en-us/library/office/ff835544.aspx
https://support.microsoft.com/en-us/kb/199505

Related

Application.ScreenUpdating = False not working switching between Excel sheets or workbooks

The function Application.ScreenUpdating = False is not working whenever switching between worksheets or workbooks in Excel. This function alone worked fine in Excel 2010, but doesn't work in later versions from what I can tell. I am now using the office 365 desktop version of excel. In these later versions, the command only prevents updating when selecting cells or doing things within a specific worksheet, but for my purposes I need a form to pull data from a second worksheet which causes flickering.
Is there a way to prevent the screen from updating/flickering with SheetB briefly when it gets activated in this macro?
Sub ActivateSheetB()
Application.EnableEvents = False
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Sheets("SheetB").Activate
End Sub
I've had the same thing happen to me forever and it's fairly annoying but from my own observation, I believe that application.screenupdating = false is still working. What I mean by that is your code is still being sped up. Other than it visually being annoying and making users think they broke excel this is still an effective method for speeding up your workbook even when switching between sheets.
Hopefully someone comes along with a better answer than mine because I'd love to know what that answer is as well xD

ScreenUpdating = False fails in Excel 2013 and 2016

Long-running, high-end Excel-based applications that I developed years ago and that run beautifully in Excel 2007 and 2010 look like Amateur Hour in Excel 2013 and 2016 because Application.ScreenUpdating = False no longer works reliably.
The screen unfreezes apparently when VBA code copies a preformatted worksheet from the macro workbook into a new workbook, although other circumstances must trigger it as well.
I’ve seen the threads on this subject that recommend “fiddling with the code” or “calling the code in a subroutine”. Unfortunately, I have to maintain hundreds of Excel applications each with thousands of lines of code and hundreds of users who are about to migrate to Office 2016, so rewriting is not an option. How can I recover Excel’s former elegance?
I wanted to leave a comment but I am not allowed to do so. Without a code sample it is very dificult to understand your problem (please see https://stackoverflow.com/help/how-to-ask and edit your question appropriately.
Here are some ideas:
- Check if your code calls for code in a different procedure, maybe the Application.ScreenUpdating is turned on outside of the procedure.
- Try this at the beginning of your procedure:
Application.Calculation = xlCalculationManual
Then, at the end of the code set it to:
Application.Calculation = xlCalculationAutomatic
It might help; however, without a code sample it is very difficult to properly help you.
Here is a technique that helps reduce flickering and preserves the StatusBar message.
Application.Cursor = xlWait
Application.ScreenUpdating = False
. . .
Set wkbNewBook = Workbooks.Add
ThisWorkbook.Windows(1).Visible = False
. . .
ThisWorkbook.Windows(1).Visible = True
wkbNewBook.Activate
Application.ScreenUpdating = True
Application.Cursor = xlDefault
We have been dealing with this problem now for a long time as my tools do show live animated charts which all of the sudden were completely static - we would have died for having at least a flickering animation.
Initially we tried to force the animation with a forced screenupdate but that did not work. Just by pure coincidence (copy pasted too many times) we stumbled into a solution which is equally unbelievable as it does seem to work. After each Application.ScreenUpdating = True we have added x3 times DoEvents. On some systems x2 times DoEvents works but x3 times does seem to be more reliable on the various office releases out there. Voila our animation came back :-)
Application.ScreenUpdating = True
DoEvents
DoEvents
DoEvents
We have not used it for the Application.ScreenUpdating = False statement but it might do some magic there. Anyway we hope that this road can help some of you finding creative functional solutions!
After looking through many forums, I believe the flicker problem is related to SDI vs MDI.
Someone suggested setting the application to not visible.
Application.Visible=False
enter code here
Application.Visible=True
This solved my flicker problem, but I didn't like how the excel application disappeared completely then suddenly reappeared for the user.
I was able to solve the issue to my liking by using a workaround this 'which window is on top' problem.
By leaving the main window alone, and forcing other workbooks to become not visible, letting the code run, then bringing them back to visible, it stopped flickering.
Application.Workbooks("yourworkbooktohide").Windows(1).Visible = False
Just remember to bring it back with =true.
Again, my script worked just fine in Excel 2010, but after "upgrading" to 2013, this flicker issue started.
For me, only "Application.ScreenUpdating = False" did not completely cure the flickering.
Calculation caused also the flickering.
Adding "Application.Calculation = xlCalculationManual" solved the flickering issue.
So, the code should be like:
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
... inportant code here....
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Nico Mijnster.
I had the same problem and, believe it or not, it was solved by unplugging and reconnecting the cable of my second monitor. This cable is using a HDMI to VGA converter.

VBA .font.bold optimization

I am formatting two different reports using the same macro. The performance between the two spreadsheets is dramatically different. The macro functions instantaneously on the first report and takes about 10 seconds on the other. I have narrowed it down to the statement which makes cell A1 bold. When the bolding statement is omitted, both spreadsheets execute the macro instantaneously. I have tried the following methods of formatting cell A1.
Range("A1").Font.Bold = True
Range("A1:A1").Font.Bold = True
With Range("A1")
.Font.Bold = True
End With
ActiveSheet.Cells(1, 1).Font.Bold = True
As far as I know, .Font.Bold = True is the only way to make a cell bold, so the problem cannot be circumvented by using another command. The above are all the ways Google has suggested calling such action. Both spreadsheets are .xls extensions. Why might one spreadsheet's performance be dramatically different when executing the same statement?
There may be a lot of reasons. The main in my opinion being that the changes require ScreenUpdating and both Worksheets use a different amount of memory to compute your Worksheet layout e.g. having shapes, pivots, charts, hidden rows etc.
To workaround this turn off ScreenUpdating before your computations. Then turn it on again like below
Application.ScreenUpdating = False
'Your code here
Application.ScreenUpdating = True
Additionally to optimize your code utilize the following:
Turn off AutomaticCalculations
Save your file as binary Excel: .xslb

Hide Text in between headers MS word 2007

I have a document that is roughly 200 pages and is essentially a list of test procedures for a specific software. Now this document has certain parts to it the pertain to different versions of the software and these parts are mixed in so their not nicely formatted in a specific order. What I would like to do is Be able to hide the parts of the document that are not needed when testing a different version. I know MS word has a font option to hide text but I would like to be able to setup up a button/hypertext link/macro that will easily hide the unneeded sections. Is this possible and how would I do it? I've started experimenting with VBA script to design my own macro but have only found a way to hide one part per shortcut hit. Is there a way to do this so all parts are effected simultaneously?
EDIT:
The document is organized like this
Version 1
Test Option button
/
Version 2
Test Option button
Check that Sample button is disabled
/
Version 1
Test Save button
/
Version 3
Test Save to USB button
/
So as you can see it's completely unorganized the code I currently have for one macro really doesn't work because instead of selecting between the two point I specify it selects the whole document.
Sub TextSelectTest()
'
' TextSelectTest Macro
' Base Test
'
With Selection.Find
.Text = "Version1"
.Forward = False
.MatchWildcards = False
.Wrap = wdFindStop
.Execute
End With
Selection.Extend
With Selection.Find
.Text = "/"
.Forward = True
.Execute
.Text = ""
End With
Selection.Extend
With Selection.Font
.Hidden = True
End With
End Sub
I don't think hiding font is most professional solution as the result is visible only for printing. But that could be the easiest in this situation especially you suggested it.
First step: set sections in your documents. It's quite easy and should be done ones in Word app. You will need to insert as many section separation marks as many parts of the document you need to manage. We will need to know which section should be/shouldn't be part of each Manual but I'll back to that later.
Second steps: Than you will need the following subroutine which will 'hide' all sections and than show appropriate ones:
Sub HideUnhide_Document_Section(secIndex As Variant)
Dim Doc As Document
Set Doc = ActiveDocument
Dim secDoc As Variant
'to hide all section first, by iteration
For Each secDoc In Doc.Sections
secDoc.Range.Font.Hidden = True
Next secDoc
'alternatively we could hide whole content without iteration:
'secDoc.Content.Font.Hidden = True
'to un-hide chosen sections
For Each secDoc In secIndex
Doc.Sections(secDoc).Range.Font.Hidden = False
Next secDoc
End Sub
And to manage your hiding process I would propose the following code:
Sub Call_Hide()
Dim arrVersion1 As Variant
'put all sections for appropriate version
arrVersion1 = Array(1, 3)
'to unhide
HideUnhide_Document_Section arrVersion1
End Sub
You could either prepare similar separate subroutine for each version or parametrize that one. It that second situation it will have to have separate arrays (arrVarsionX) for each Version of your manuals.

What Excel VBA actions are possible on hidden worksheets or workbooks?

Hidden worksheets/workbooks have some limitations to what can be done in VBA code, like most Select and Selection statements, and anything coming from ActiveSheet, but I can't seem to find any list of what the limitations are.
Google, the built-in documentation in the help system, and MSDN's website have all failed me. Can anyone point me in the right direction?
Edit:
The workbook is opened with
Set WB_Master = Workbooks.Open(Filename:=PATH_Master, ReadOnly:=False)
and then hidden with
WB_Master.Windows(1).Visible = False
From the Visual Basic for Applications help:
When an object is hidden, it's removed from the screen and its Visible property is set to False. A hidden object's controls aren't accessible to the user, but they are available programmatically to the running application, to other processes that may be communicating with the application through Automation, and in Windows, to Timer control events.
Not much help there I'm afraid, and I couldn't find much else through Google.
As you said yourself, the Select method and Selection Property don't work on a hidden Worksheet, they should work on a hidden Workbook though. (Please correct me if I'm wrong.) In general however, it's not always all that efficient to select ranges in worksheets anyway, you are better off working with the Range property (which does work on a hidden worksheet).
EDIT:
The following code will change the color of A1:A8 to Cyan even when the Worksheet is not visible:
Dim book2 As Workbook
Set book2 = Workbooks.Open("C:\Book2.xls")
book2.Worksheets("Sheet1").Visible = False
book2.Windows(1).Visible = False
With book2.Worksheets("Sheet1").Range("A1:E8").Interior
.ColorIndex = 8
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
End With
book2.Windows(1).Visible = True
book2.Worksheets("Sheet1").Visible = True
You can get around any limitations on hidden sheets by unhiding them without the user realizing it, doing whatever you need to, and then hiding them again.
This example assumes that Sheet2 is hidden.
Sub DoStuffToAHiddenSheetWithoutTheUserKnowingIt()
'turns off screen repainting so the user can't see what you're doing
'incidentally, this dramatically speeds up processing of your code
Application.ScreenUpdating = False
'note that if you're stepping through your code, screenupdating will be true anyway
'unhide the sheet you want to work with
Sheets("sheet2").Visible = True
'do whatever you want here, including selecting cells if you want
'Scagnelli is right though, only select cells if you have to
'when you're finished, hide the sheet again
Sheets("sheet2").Visible = False
'make sure you turn screenupdating back on, or Excel will be useless
Application.ScreenUpdating = True
End Sub
Another useful trick if you want your sheets hidden is to set them to xlVeryHidden, which will prevent them from being listed to the user if they try to unhide them through the menu or ribbon.