Apache POI and SUMPRODUCT formula evaluation - apache

I have a template XLS file that I load with Apache POI and write loads of data in it, then save it as another file.
I have formulas in my XLS file like this:
=SUMPRODUCT((DS!B:B="IN_THIS_ONLY")*(DS!D:D="New trade"))
also tried
=SUMPRODUCT(0+(DS!B:B="IN_THIS_ONLY"),0+(DS!D:D="New trade"))
these evaluate correctly if I press Enter on the cell in Excel.
However, simply calling
HSSFFormulaEvaluator.evaluateAllFormulaCells(workbook);
does not seem to evaluate them, neither does pressing on the "Calculate now" button in Excel - so I guess this is a special formula or function.
The other, more conventional COUNTIFs and SUMIFs work fine, however these do not allow multiple conditions to be specified.
POI does not support array formulas.
Is there any way to make these work. I'm using POI version 3.7.

One can press CTRL-ALT-F9 to manually re-evaluate all formulas forcefully in Excel.
And here is the trick to make it work automatically on workbook open.
Add the following to your formula:
+(NOW()*0)
so for example, my SUMPRODUCT above becomes
=SUMPRODUCT((DS!B:B="IN_THIS_ONLY")*(DS!D:D="New trade"))+(NOW()*0)
And this works! Excel now recalculates my special formula cells on open.
The reason for this is that NOW() is a volatile function. Here is where I learned about this: http://msdn.microsoft.com/en-us/library/bb687891.aspx
Application.CalculateFull also works, but only in Excel 2007 and later (and of course, one must enable macros to run). Unfortunately, in my case even though I use Excel 2007 my workbook will be opened by Excel 2003 users as well, so this was not an option.

Is SumProduct an array based formula function?
If so, that would explain the issue. One option is to contribute a patch to POI to add the missing support. There's been some discussion on the dev list and bugzilla on what's needed, and if you were to post to the dev list then we'd be happy to help you get started.
Otherwise, you could just set the formula recalculation flag and get Excel to recalculate the value on load

Related

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.)

Problems recording long Excel formula with macro recorder

I'm trying to record a macro of my formula in Excel and it gives me a syntax error.
This is the formula:
=IF(AND(OR(B2="toola",B2="toola1",B2="toola2",B2="SFx200"),OR(H2="Q1",H2="Q2",H2="Q3",H2="Q4")),CONCATENATE(H2," "," ",IF(I2="p","pre","")," ","SFx","-",IF(A2="",0,A2)),IF(AND(OR(B2="toolb",B2="toolb1",B2="toolb2",B2="toolb3",B2="yoolb4",B2="toolb4",B2="toolb5",B2="toolb6",B2="toolb7",B2="toolb8",B2="toolb9",B2="toolb10",B2="toolb11",B2="toolb12"),OR(H2="Q1",H2="Q2",H2="Q3",H2="Q4")),CONCATENATE(H2," ",IF(I2="p","pre",""),"-"," ",IF(A2="",0,A2)),IF(AND(OR(B2="up",B2="up1",B2="up2",B2="up3",B2="up4",B2="up5",B2="Up6",B2="up7"),OR(H2="Q1",H2="Q2",H2="Q3",H2="Q4")),CONCATENATE(H2," ","UP","-",IF(A2="",0,A2)))))
I know that it is big, but why won't the macro recorder properly record it?
The macro recorder is useless with long formulas as it overwrites some of the formula string when it adds in line continuations for the VB editor. You'll either need to edit the code yourself or shorten the formula - e.g. use things like OR(H2={"Q1","Q2","Q3","Q4"}) rather than OR(H2="Q1",H2="Q2",H2="Q3",H2="Q4")
Also if possible replace something like this:
OR(B2="toolb",B2="toolb1",B2="toolb2",B2="toolb3",B2="yoolb4",B2="toolb4",B2="toolb5",B2="toolb6",B2="toolb7",B2="toolb8",B2="toolb9",B2="toolb10",B2="toolb11",B2="toolb12")
with this
LEFT(B2,5)="toolb"
When you have more than 7 times if excel does not want to work. Thus, you should go around it. With Select Case.
Or something like this, when the nested ifs are in a formula:
https://www.techonthenet.com/excel/macros/if_custom.php
You can go up to as many cases as you need. Then simply use the custom formula.

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

vba command to paste special KeepSourceFormatting(K) in powerPoint

i am trying to take a cell range from excel and copy it to powerpoint2010. However I do not want to use the Embedded format but rather the KeepSourceFormatting one. I tried the following command
ActiveWindow.View.PasteSpecial DataType:=ppPasteOLEObject, Link:=msoFalse
but this still creates an object that launches excel to edit the contents.
basically I want to paste a table of formated data from excel to powerpoint and maintain its appearance but still be able to edit the contents in powerpoint.
any ideas?
There are following options for DataType:
ppPasteEnhancedMetafile which allows edition each of separate field of the table (rather pure solution)
ppPasteMetafilePicture similar option
ppPasteOLEObjectwhich you know
I can't see any other option.

Need to Update External References in an Excel Sheet while a Macro is Running

I have an excel macro that sets Cells to an external location.
Range(NamedReference) = "='http://webaddress/ExcelSheet.xlsx'!NamedReference
Other cells use that location to calculate new values.
"A1" = NamedReference + 1
The problem is that I need to read the new calculated values back into the macro to export data, but the external link has not yet been calculated to any value. It is a #NAME? until the macro is done running. Is there any way to force excel to get those values during the macro run time?
I have tried a variety of things including
Calculate
CalculateFull
Any help would be appreciated. My current solution is to just close the macro on error and have the user re run the macro, but it is really kludgey.
**Edit: Forgot equals sign in formula
You could try
ActiveWorkbook.UpdateLink Name:=ActiveWorkbook.LinkSources
See on MSDN