Excel 2016 VBA - Slow performance - vba

Our company recently upgraded to Office 2016 and a lot of people in the office are experiencing very slow calculation speeds (like 1%/s if their lucky).
I have tried restarting, repairing Office, removing the add-ins, etc. I narrowed it down to a file having VBA in it. For example, I created two files: both have two columns of 10k observations of hard-coded numbers and one calculated column. The only difference is that file #1 uses a predefined formula (below) while file #2 uses a UDF (below) and is saved as .xlsm instead of .xlsx.
File #1 (.xlsx)
C1 = 100 * A1 + B1
File #2 (.xlsm)
C1 = UDF(A1, B1)
Where UDF is defined as:
Function UDF(x, y)
UDF = 100 * x + y
End Function
Are there any steps I can try to fix this issue? Not everyone is experiencing it either. I've sent the VBA file around and for those that it calculates fast (i.e. instantaneously) I had them screenshot their VBA references but they are the same as what I have.

If starting Excel in Safe Mode cures the problem, it has to be down to an add-in or startup file - or some combination of them. Disable them all and see if that fixes it, then you can re-enable one by one to try and narrow down the culprit.

Related

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!

Hidden rows not hidden after copy paste in excel

I am copying contents of an excel workbook to another workbook.My sheet has few hidden rows which has to be kept hidden in the target workbook as well.
I am using the below lines of code to copy the data :
'Set rngCopyRange = wbSource.ActiveSheet.Cells
rngCopyRange.Copy
This works fine in Win 10 64 bit,Office 2013 64bit or Office 2016 32 bit combination
But in windows 10 64b , Office 2010 32b or 2013 32b combination,the hidden rows are not hidden.
Is this an issue with excel version?Can someboby help me to sort this issue?
How odd. I'm using 2013(64bit) and if I use your code I DO NOT copy across the hidden property of each row to the target.
I think the issue you're getting though is that you're copying across a range that doesn't extend across all columns, so setting the row height (i.e. for all columns) would be counter-intuitive.
If you add .EntireRow to your copy range, the row height will come across:
Set rngCopyRange = wbSource.ActiveSheet.UsedRange.EntireRow
In 99%* of the cases where people hide rows and then copy and paste
them to another location they don't actually need the hidden rows to
exist in the destination
... so I'm taking a punt and offering this as a solution:
rngCopyRange.SpecialCells(xlCellTypeVisible).Copy
*Like all good statistics, I made this one up
This is just a speculation, but if you are using wbSource.ActiveSheet.Cells, aren't you copying all the cells in that worksheet, including the hidden ones ? Maybe the logic is a bit different for the Office versions, though I still new to VBA.

Change sheet name in a link to another workbook

This is probably a very simple question but I am having trouble solving it.
Every month I need to update the data in a workbook based on what I have in another one.
In the source workbook the data is separated in different sheets for each month (Sheet name ex: Forecast Jan, Forecast Feb ...).
In the destination workbook, my links are pretty simple:
=+'Q:\ ... \ [CLH_2016_01 Displaced inventory 2015-12-14.xlsm]**Forecast Aug**'!$C$65
What I am looking for is a way to change Forecast Aug with Forecast Sep.
I have tried the easy way with Ctrl + H but I have over 4000 formulas to change and it takes a while (almost an hour if it does not crash before the end).
Thanks in advance!
you can use indirect :
=INDIRECT("'Q:\ ... \ [CLH_2016_01 Displaced inventory 2015-12-14.xlsm]Forecast "&TEXT(TODAY(),"mmm")&"'!$C$65")
However, this will work only if the external workbook is open, which might be a problem if you have several different workbooks.
In that case, the workaround I had done in my previous job was to use INDIRECT.EXT, a function that performs INDIRECT and is able to check in closed workbooks.
However, this function is included in Morefunc.xll which is an external library, so you will require an installation.
Based on the solutions given by #Siddharth Rout and #Jeeped, here are two ways of improving the process:
-Change calculations to manual and then try Ctrl + H
-Your Find & Replace will likely be much quicker if you open the external file into the same application instance. The extended time to update would seem to be from re-evaluating each change individually.

Decimal parsing differences on separate environments

Evening,
I'm bashing my head against a wall with the following problem:
I'm loading numbers from cells from a Number column with size=16
and decimal places = 2 inside adBase III .dbf file.
These numbers, when viewed with a DbfViewer appear as: 12345.12, where there is no thousands separator and the decimal
separator is ..
I parse the number from the cell in the database using decimal.parse(val).
I do stuff with that number.
I am using the ClosedXML library to paste the number into an .xlsx Excel file cell with the following formula: "=R[-1]C * 100/" & val where val is the value I obtained from the dBaseIII database file. This is done with the following statements:
Dim formula as String = "=R[-1]C * 100/" & project.TotalIncome(i)
cell.FormulaR1C1 = formula.
I am using two programming environments:
A Windows 8.1 machine with Visual Studio 2013 Community and Office 2010.
A Windows 8.1 machine with Visual Studio 2013 Ultimate and Office 2013.
I have made sure that both environments have the same Language, Date, Time and Number format, both for Windows and Office.
When I build and execute the program from the Option 1 Environment, everything pastes fine inside the Excel file. I navigate to the cell containing the formula, and whether or not the value obtained had decimal places, the formula is there.
However, If I build and execute the program from the Option 2 Environment, I get a:
Removed Records: Formula from /xl/worksheets/sheet.xml part
Removed Records: Formula from /xl/calcChain.xml part (calculation properties)
I tried adding a breakpoint in Environment 2, opening the Locals window and editing those values which had decimal places and everything worked as intended, whereas when I use Environment 1 I have no trouble whatsoever when the value has decimal places.
I have tried the following (in Environment 2):
Dim nfi As NumberFormatInfo = New CultureInfo("es-ES", False).NumberFormat
nfi.NumberDecimalSeparator = ","
value = Decimal.Parse(row("VALUECOL"), nfi)
also:
value = Decimal.Parse(row("VALUECOL"), New CultureInfo("es-ES"))
To no avail.
I have opened the XML file containing the Excel Sheet info in Environment 2 and found this:
<x:c r="L101" s="41">
<x:f>L100 * 100/57125,71</x:f>
</x:c>
Whereas the definitions for the same XML file created by the Environment 1 has the following cell value:
<x:c r="L101" s="41">
<x:f>L100 * 100/57125.71</x:f>
</x:c>
So, is it a Visual Studio Locale thing (which both have the same, as far as I can see), or am I missing something else?
EDIT: Printing out the current Locale with:
Console.WriteLine(CultureInfo.CurrentCulture.Name)
yields the same es-ES on both Environment 1 and Environment 2.
EDIT 2:
Taken from: Microsoft Office XML formats. Defective by design.
To save them time, Microsoft chose to store XML using the US English
locale regardless of all settings above. [...]
Also, for Excel formulas, it means the formula names are US English
formula names, [...] it implies you are willing to work with US English
function names (plus US English separators, ...).
So basically it all boils down (I believe) to a pre localisation of the decimal value into the Excel XML taking into account something, somewhere.
In Environment 2, any other (non-formula) value I write to the Excel file appears in the XML as an en-US localised value (i.e. 12345.12). Most of them brought in by a dataTable import. However, since writing a formula requires the input of a string, and Visual Studio applies locale settings to said string, it ends up as 12345,12 in the Excel XML, which results in the previously mentioned errors.
So, what on earth is Visual Studio taking from Environment 1 that is different from Environment 2? All possible UI localisation options are exactly the same in both machines...
I had a similar issue before, and found that there was a different dll file in my project references. The dll's were named the same, I only noticed because of a file size difference. Once I manually linked to the same one on both Dev machines, I got the expected results.
Like I said, my issue was different... But it did also involve excel files, and I did have Excel 2010 on one Dev machine and 2013 on the other.
I don't even know if this qualifies as an answer since I still have no clue about where's the localisation variable that Environment 1 has different from Environment 2.
However, It seems Visual Studio -when using different localisations- deals internally with de-localised decimal variables, but with localised string variables. Even when checking the locals panel during debugging, the value of a decimal number stored in a dictionary entry will appear as its localised version on the keyValuePair entry, and as a de-localised en-US value when expanded:
Hence, when outputting a dataTable as a whole to the Excel file, it's written onto the XML as en-US values. On the other hand, when outputting a formula (a.k.a. a string) it pours over the localised version of the associated decimal value.
Conclusion: When dealing with Office files in localised systems, just write the data as de-localised (i.e. en-US) and let the software localise it for you.
Ended up doing the following dirty patch:
Dim formula As String = "=R[-1]C * 100/" & project.TotalIncome(i).ToString().Replace(",", ".")

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