Force full calculation of entire workbook in Coldfusion / Apache POI - coldfusion

Given a workbook with cross-sheet formulas generated by Coldfusion 9 via Apache POI.
I want to programmatically force an entire workbook to do a "full calculation with dependency tree rebuild" before saving the workbook to disk.
So that when my end-users open the spreadsheet, they do not have to press Ctrl-Alt-Shift-F9.
How do I accomplish this in coldfusion?
References:
http://adobe.ly/HbLBZo
http://poi.apache.org/spreadsheet/eval.html
http://bit.ly/HJJA3Q

Unfortunately there is no easy answer to this one.
Option 1:
I think the shortest route is to use CreationHelper.createFormulaEvaluator().evaluateAll(). Unfortunately, it is not available in CF9. That method was added in a later version of POI than the one shipped with CF9. The same applies to setForceFormulaRecalculation(). You could probably use the JavaLoader.cfc to load a newer version of POI. Then you would have access to those methods. But that may be more involved than you want for this one task.
Option 2:
Failing that, if you know the proper sequence you could iterate through the sheets and recalculate the formulas for each one:
wb = sheet.getWorkBook();
evaluator = wb.getCreationHelper().createFormulaEvaluator();
// you could also use an array of sheet names instead
for(sheetNum = 0; sheetNum < wb.getNumberOfSheets(); sheetNum++) {
poiSheet = wb.getSheetAt(sheetNum);
rows = poiSheet.rowIterator();
while (rows.hasNext()) {
r = rows.next();
cells = r.cellIterator();
while (cells.hasNext()) {
c = cells.next();
if (c.getCellType() == c.CELL_TYPE_FORMULA) {
evaluator.evaluateFormulaCell(c);
}
}
}
}
Option 3:
Another possibility is to populate a template with a macro which automatically recalculates when the workbook opens. The obvious disadvantage is it relies on a macro. But since it is performed by Excel itself, it is probably the most reliable/robust option.

Related

Is it possible to keep a shared state between windows when using UDFs in BigQuery?

This is a follow up question to my previous question about being able to emulate aggregate functions (like in PGSQL) in BigQuery.
The solution propsed in the previous question does indeed work for cases where the function applied on each window is independant of the previous window - like calculating simple average etc., But when calculating recursive functions like exponential moving average, where the formula is:
EMA[i] = price[i]*k + EMA[i-1]×(1−k)
Using the same example from the previous question,
CREATE OR REPLACE FUNCTION temp_db.ema_func(arr ARRAY<int64>, window_size int8)
RETURNS int64 LANGUAGE js AS """
if(arr.length<=window_size){
// calculate a simple moving average till end of first window
var SMA = 0;
for(var i = 0;i < arr.length; i++){
SMA = SMA + arr[i]
}
return SMA/arr.length
}else{
// start calculation of EMA where EMA[i-1] is the SMA we calculated for the first window
// note: hard-coded constant (k) for the sake of simplicity
// the problem: where do I get EMA[i-1] or prev_EMA from?
// in this example, we only need the most recent value, but in general case, we would
// potentially have to do other calculations with the new value
return curr[curr.length-1]*(0.05) + prev_ema*(1−0.05)
}
""";
select s_id, temp_db.ema_func(ARRAY_AGG(s_price) over (partition by s_id order by s_date rows 40 preceding), 40) as temp_col
from temp_db.s_table;
Storing state variable as a custom type is very easy in PGSQL and is a part of the aggregate function parameters. Would it be possible to do emulate the same functionality with BigQuery?
i don't think it can be done generically for BigQuery and rather wanted to see the specific case and see if some reasonable workaround is possible. Meantime, again recursiveness and aggregate UDF is something that is not supported [hopefully yet] in BQ, so you might want to submit respective feature request(s).
Meantime checkout BQ scripting but i don't think your case will fit there

Exporting an oracle table dynamically to a flat file

I am trying to build a C++ program using occi libraries that will take a select statement or a table name as an input and turn it into a delimited file. However, looking at the documentation, I can't find a way to export all columns of a query result into a file. Almost all examples I found were along the following lines
string query = "SELECT col1 FROM table1";
stmt = con->createStatement(query);
res = stmt->executeQuery();
while (res->next())
{
outfile<<res->getInt(1)<<endl;
}
What i want to do is: Do a select * and then export the full row to the file in one go without specifying the type for each column, but I haven't been able to find something that does this.
I know that row-by-row exports are not really efficient for large sets, but I want to make this work before optimizing it.
Does anyone have any ideas around how to do this efficiently?
I don't think that you will find something like this "in the box" while using OCCI.
However using STL you can push to a stringstream the result of every iteration and when the rs->next() is NULL you can append the stringstream in the file.
I found that there is no way to do this without iterating over the metadata object at least once. Since I only need to do this once per query execution I ended up writing the attribute types and column positions to a map and using that map within the result set loop to read data. Here's the code I used:
res = stmt->executeQuery();
vector<oracle::occi::MetaData> meta = res->getColumnListMetaData();
map<int, int> mapper;
for (int i=0; i < meta.size(); i++) {
mapper[i] = meta[i].getInt(oracle::occi::MetaData::ATTR_DATA_TYPE);
}

Applying conditional formatting with CFSpreadsheet

In continuation of a previous thread, I've reached pretty close to where I want and have learned a lot. I'm under CF10 on a MSSQL Server 2008 environment. I have a report I'm generating using cfspreadsheet and then spitting out values based on whether a user has an app enabled it will be output as "Yes" and if not output as "No" in the excel spreadsheet.
Problem is, I need to make it a little easier on the eye and so I wanted to see if it was possible to apply conditional formatting to where if the 3 columns with 3 different apps is Y then it will be green and if N it will be red.
Any suggestions or examples would be great, thanks!
Like I mentioned in your other thread, if you return bit values (not strings), it is simple to apply a custom cell format. But you must use the spreadsheet functions, rather than cfspreadsheet (which does not support custom formatting).
Here is an expanded example to demonstrate how you could incorporate conditional color formatting:
<cfscript>
// build sample query
// note: values must be numeric and NOT text/varchar
qData = queryNew("");
queryAddColumn(qData, "AppNameAlpha", "bit", listToArray("0,0,1,0,1"));
queryAddColumn(qData, "AppNameBeta", "bit", listToArray("1,1,0,0,1"));
// create sample sheet
sheet = spreadsheetNew();
spreadsheetAddRows(sheet, qData);
// apply colorized yes/no format
spreadsheetFormatColumns(sheet, {dataformat='[Green]"Y";;[Red]"N"'}, "1-2");
spreadsheetWrite(sheet, "c:/path/to/sheet.xls", true);
</cfscript>
The "dataformat" uses the first three sections of Excel's custom number formatting: <positive><negative><zero>. Translated:
[Green]"Y"; // <positive values>: display "Y" in green
; // <negative values>: do nothing extra
[Red]"N" // <zero values>: display "N" in red
The function you are looking for is SpreadsheetFormatCell()

Number formatting in pivot table with Aspose.Cells

I am creating a pivot table in excel sheet by aspose.cells. I want the values to be formatted as Accounting, with a symbol, a comma and 2 decimal places. Is this possible with aspose.cells? Please suggest how to do this with Aspose.Cells and c#.
If you need Accounting number formatting for the PivotField, you may try to use the following numeric formatting using PivotField.Number attribute instead.
pivotTable.DataFields[0].Number = 43; //You may also try it with 44 if it suits your needs.
Alternatively you may try to use the following formatting string for NumberFormat custom attribute of PivotField. You may also check in MS Excel to get your desired custom strings to try with NumberFormat property.
_($* #,##0.00_);_($* (#,##0.00);_($* "-"??_);_(#_)
If you still face any confusion/issue, can you please share the sample Excel file in which you may manually set the desired number formatting for the Pivot Table fields in MS Excel, and share the file with us, so that we can test the scenario at our end.
Furthermore, can you please share the code/sample application with the template files (input, output and expected output file etc.). The files can also be shared in Aspose.Cells product support forum.
Please try using PivotField.NumberFormat property to specify his desired formatting, see the code segment below for reference:
//Specify the number formatting to the first data field added.
pivotTable.DataFields[0].NumberFormat = "$#,##0.00";
Moreover, we also recommend you use our latest version of Aspose.Cells for .NET 7.4.0 in which we made some more enhancements regarding PivotTables.
PS, I am working as Support developer / Technical Evangelist at Aspose.

How to iterate over all the page breaks in an Excel 2003 worksheet via COM

I've been trying to retrieve the locations of all the page breaks on a given Excel 2003 worksheet over COM. Here's an example of the kind of thing I'm trying to do:
Excel::HPageBreaksPtr pHPageBreaks = pSheet->GetHPageBreaks();
long count = pHPageBreaks->Count;
for (long i=0; i < count; ++i)
{
Excel::HPageBreakPtr pHPageBreak = pHPageBreaks->GetItem(i+1);
Excel::RangePtr pLocation = pHPageBreak->GetLocation();
printf("Page break at row %d\n", pLocation->Row);
pLocation.Release();
pHPageBreak.Release();
}
pHPageBreaks.Release();
I expect this to print out the row numbers of each of the horizontal page breaks in pSheet. The problem I'm having is that although count correctly indicates the number of page breaks in the worksheet, I can only ever seem to retrieve the first one. On the second run through the loop, calling pHPageBreaks->GetItem(i) throws an exception, with error number 0x8002000b, "invalid index".
Attempting to use pHPageBreaks->Get_NewEnum() to get an enumerator to iterate over the collection also fails with the same error, immediately on the call to Get_NewEnum().
I've looked around for a solution, and the closest thing I've found so far is http://support.microsoft.com/kb/210663/en-us. I have tried activating various cells beyond the page breaks, including the cells just beyond the range to be printed, as well as the lower-right cell (IV65536), but it didn't help.
If somebody can tell me how to get Excel to return the locations of all of the page breaks in a sheet, that would be awesome!
Thank you.
#Joel: Yes, I have tried displaying the user interface, and then setting ScreenUpdating to true - it produced the same results. Also, I have since tried combinations of setting pSheet->PrintArea to the entire worksheet and/or calling pSheet->ResetAllPageBreaks() before my call to get the HPageBreaks collection, which didn't help either.
#Joel: I've used pSheet->UsedRange to determine the row to scroll past, and Excel does scroll past all the horizontal breaks, but I'm still having the same issue when I try to access the second one. Unfortunately, switching to Excel 2007 did not help either.
Experimenting with Excel 2007 from Visual Basic, I discovered that the page break isn't known unless it has been displayed on the screen at least once.
The best workaround I could find was to page down, from the top of the sheet to the last row containing data. Then you can enumerate all the page breaks.
Here's the VBA code... let me know if you have any problem converting this to COM:
Range("A1").Select
numRows = Range("A1").End(xlDown).Row
While ActiveWindow.ScrollRow < numRows
ActiveWindow.LargeScroll Down:=1
Wend
For Each x In ActiveSheet.HPageBreaks
Debug.Print x.Location.Row
Next
This code made one simplifying assumption:
I used the .End(xlDown) method to figure out how far the data goes... this assumes that you have continuous data from A1 down to the bottom of the sheet. If you don't, you need to use some other method to figure out how far to keep scrolling.
Did you set ScreenUpdating to True, as mentioned in the KB article?
You may want to actually toggle it to True to force a screen repaint. It sounds like the calculation of page breaks is a side-effect of actually rendering the page, rather than something Excel does on demand, so you have to trigger a page rendering on the screen.