I am getting the exception Tab Formula for tab, t4 is invalid. Formula = [t2]+[t1]: Tag Label must be unique.
I have checkbox, a fundname and amount to invest in fund.
if user check the checkbox he need to fill the amount in amount box and there is total amount calculated based on the no of amount box has amount entered.
Evertything is working fine but only issue is with formula field. it is throwing an exception formula is invalid.
below is what I am using for showing the calculation:
var fullAnchor4 = new Tab
{
Type = TabTypeCode.Custom,
CustomTabType = CustomTabType.Formula,
CustomTabTypeSpecified = true,
AnchorTabItem =
new AnchorTab
{
AnchorTabString = "tbx4_1_text",
XOffset = -10,
YOffset = -5
},
CustomTabWidth = 100,
CustomTabWidthSpecified = true,
Formula = "<formula>[t2]+[t1]</formula>"
};
fullAnchor4.DocumentID = "1";
fullAnchor4.PageNumber = "1";
fullAnchor4.RecipientID = "1";
fullAnchor4.TabLabel = "t4";
fullAnchor4.RoundDecimalPlaces = 2;
runningList.Add(fullAnchor4);
is there something I am doing wrong?
EDIT--
Attached the raw request. removed sensitive info
http://wikisend.com/download/218254/RawRequest 1.txt
Per DocuSign's documentation, Formula Fields cannot be Anchored (link below). Unsure if this is still true today. Also, I noticed in your document you have the Formula Field's Anchor String listed twice. You have it also listed where an email address would be placed "Email Address: tbx4_1_text". Once I removed that duplicate string from the document the call was successful and the Formula Field appears to be calculating correctly.
https://www.docusign.com/support/classic/documentation/cdse-user-guide/advanced-sending/using-the-calculated-fields-feature
Your Formula value should not have XML tags in it. Your resulting API request looks like this:
<Formula><formula>[t2]+[t1]</formula></Formula>
You should use something like this:
Formula = "[t2]+[t1]"
The resulting XML will end up like this:
<Formula>[tw]+[t1]</Formula>
Related
I have generated an Excel table using PHPSpreadsheet including the style and the autofilter:
The problem is when I sort the data by the second and third columns, the table formatting is gone. This is how it looks like compared if I use Table Style directly from Excel (using Home-> Format as Table):
Is there any way to keep the formatting when I sort the table generated from PHPSpreadsheet?
Relevant PHP Code:
for ($rowNumber = 0, $rowNumberMax = sizeof($rows); $rowNumber < $rowNumberMax; $rowNumber++) //rows (all data)
{
$columnNumber = 0; //1 = A
for ($i = 0, $j = sizeof($tableColumns); $i < $j; $i++) //loop through table header label
{
foreach ($rows[$rowNumber] as $rowKey => $rowValue) //loop through single row data
{
if($tableColumns[$i] == $rowKey)
{
$sheet->setCellValueByColumnAndRow($columnNumber + 1, ($rowNumber + 5), $rowValue);
$currentCell = Utilities::num2alpha($columnNumber) .''. ($rowNumber + 5);
$sheet->getStyle($currentCell)->getNumberFormat()->setFormatCode('#');
$sheet->getStyle($currentCell)->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT);
if(($rowNumber+5) % 2 == 0)
{
//even row
$sheet->getStyle($currentCell)->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setARGB('ffd9e1f2');
}
else
{
//odd row
}
$columnNumber++;
break;
}
}
}
}
//set autofilter
$headerFirstCellPosition = 'A4';
$tableLastCellPosition = Utilities::num2alpha(sizeof($tableColumns) - 1) . '' . (sizeof($rows) + 4);
$sheet->setAutoFilter($headerFirstCellPosition . ':' . $tableLastCellPosition);
The problem is you were just applying formatting to the cells based on if the row was even or odd, but it wasn't actually replicating a table in Excel. You would find the same result in Excel if you just formatted every other row like you did with your PHP code, where the "table" format would get lost.
Somebody just recently implemented a first pass of the actual table feature in Excel: https://github.com/PHPOffice/PhpSpreadsheet/pull/2671
You need to be on PHPSpreadSheet version 1.23.0 in order to be able to use this.
Using that, you would have to modify your code but you can go to the Samples section in the code area and view how to implement it: https://github.com/PHPOffice/PhpSpreadsheet/tree/master/samples/Table
https://github.com/PHPOffice/PhpSpreadsheet/blob/master/samples/Table/01_Table.php
Here is the relevant code (I removed some of the lines and added additional comments from the 01_Table.php sample at the link provided).
Table styles can be found here: https://github.com/PHPOffice/PhpSpreadsheet/blob/master/src/PhpSpreadsheet/Worksheet/Table/TableStyle.php
// Create Table
$table = new Table('A1:D17', 'Sales_Data');
// Create Table Style
$tableStyle = new TableStyle();
// this line is the style type you want, you can verify this in Excel by clicking the "Format as Table" button and then hovering over the style you like to get the name
$tableStyle->setTheme(TableStyle::TABLE_STYLE_MEDIUM2);
// this gives you the alternate row color; I suggest to use either this or columnStripes as both together do not look good
$tableStyle->setShowRowStripes(true);
// similar to the alternate row color but does it for columns; I suggest to use either this or rowStripes as both together do not look good; I personally set to false and only used the rowStripes
$tableStyle->setShowColumnStripes(true);
// this will bold everything in the first column; I personally set to false
$tableStyle->setShowFirstColumn(true);
// this will bold everything in the last column; I personally set to false
$tableStyle->setShowLastColumn(true);
$table->setStyle($tableStyle);
Also make sure that you include the following to be able to use these:
use PhpOffice\PhpSpreadsheet\Worksheet\Table;
use PhpOffice\PhpSpreadsheet\Worksheet\Table\TableStyle;
Implementing that into your code will then allow you to sort using the auto filters and keep the formatting like you are expecting.
There are a few caveats such as:
Note that PreCalculateFormulas needs to be disabled when saving spreadsheets containing tables with formulae (totals or column formulae).
Also, as I am actually currently working on doing this, it doesn't look like you can apply an autofilter and have a table at the same time at this point.
That does appear to be on the todo list though, as the first link I provided the contributor has "Filter expressions similar to AutoFilter."
Otherwise, that should get you what you want and aside from being able to auto filter prior to creating the Excel file, it has worked well in my small testing.
Edit to add:
I think you can actually simplify your code a bit by using the functionality of PHPSpreadsheet to create a a spreadsheet from an array.
Documentation from PHPSpreadsheet can be found here: https://phpspreadsheet.readthedocs.io/en/latest/topics/accessing-cells/#setting-a-range-of-cells-from-an-array
You'll need to change it so that the array that is holding the info starts with your headers, so I believe that would look similar to this for your code:
$rows = [
['header1', 'header2', 'header3', 'header4']
];
Then you can populate the $rows array with your data from the rows either with a loop or just a single declaration depending on what you are putting in there, but basically using the below to populate the array.
$rows[] = [
$field1Data,
$field2Data,
$field3Data,
$field4Data
];
After you do that, you can then generate the spreadsheet using the following:
$sheet->getActiveSheet()
->fromArray(
$rows, // the data to set
NULL, // array values with this value will not be set
'A1', // top left coordinate of the worksheet range where we want to set these values (default is A1)
true // adds 0 to cell instead of blank if a 0 is the value
);
After doing the above, you can then add the code to create the table I posted and then save the file and you should be good.
Also, if you are in a situation where you still need to use the autofilter (for instance if you want to pre-filter the file on one or more columns which at this point you can't use a table when doing), you can make the autofilter call a bit easier.
// determine the the number of rows in the active sheet
$highestRow = $spreadsheet->getActiveSheet()->getHighestRow();
// get the highest column letter
$highestColumn = $spreadsheet->getActiveSheet()->getHighestColumn();
// set autofilter range
$spreadsheet->getActiveSheet()->setAutoFilter('A1:'.$highestColumn.$highestRow);
I realize the additional edit goes beyond the question, but figured I'd point it out since there are some built-in methods that you could use to reduce some of your code.
-Matt
I have a custom function that hides/shows columns in my tabulator. The column I click on is supposed to hide and several other columns are shown. I have this function working correctly from onclick on an object in a custom cell formatter, but I would like to call it from clicking on the column header. It works except that I can't seem to get a handle of the column I clicked on from column header in order to hide the column.
I'm trying to get the column object and pass it to my function so I can hide that column while I show the others. I'm open to other ways to do this.
this works (cell formatter)
var showForecastCell = function(cell, formatterParams, onRendered){
...
span.onclick = function(){showForecast(cell.getColumn())};
return span
}
this doesn't work (column titleFormatter)
var showForecastHeader = function(t,e,o,i,n){
...
span.onclick = function(){showForecast(t.getColumn())};
return span
}
Is there any way to pass the column object from clicking on the column header? otherwise, if there is a simpler way to hide the column after clicking on the header, I am open to suggestions. I must admit that javascript isn't my strongest language and if I am overlooking something basic, please let me know.
You can check this JsFiddle it hides all other columns except the one you click
for Column call backs you can check documentation here and here
const hideAllButThis = function(e, column) {
const showField = column._column.field;
const columns = column._column.table.columnManager.columns;
for (let i = 0; i < columns.length; i++) {
if (columns[i].field !== showField) {
table.hideColumn("" + columns[i].field + "")
}
}
};
i am having difficulties with open xml sdk:
i am trying to generate excel file with several columns that have numbers and i want to have total sum at the end
i have tried to Generate Table Definition Part Content and inside define every column (id, name etC). If column has true for TotalColumn, it adds code (rough example)
var column = new TableColumn{
id = 1,
name = "example",
TotalsRowFunction = TotalsRowFunctionValues.Sum,
TotalsRowFormula = new TotalsRowFormula("=SUBTOTAL(109;[" + rowName + "])")
};
I can't get it to work, when i open excel it reports error, but it doesn't explicitly says what the problem is... I tried with microsoft validator but can't figure anything out...
I'd appreciate any help / example code since i can't google anything out
EDIT:
i use this at the end:
workbookPart.Workbook.CalculationProperties.ForceFullCalculation = true;
workbookPart.Workbook.CalculationProperties.FullCalculationOnLoad = true;
Why not use a cell formula?
E.g.
cell.DataType = new EnumValue<CellValues>(CellValues.Number);
cell.CellFormula = new CellFormula(string.Format("=SUBTOTAL({0};[{1}])", "109", rowName));
//This will force a full recalculation of all the cells
workbookPart.Workbook.CalculationProperties.ForceFullCalculation = true;
workbookPart.Workbook.CalculationProperties.FullCalculationOnLoad = true;
I ended using EPPlus for this as it seems to be working simple and efficient
In my rdlc report have following columns
SlNo, Item, Uom, Qty, Rate, Amount
Here the Amount field is a formula (Rate*Qty)
The report is working fine, and when i export to excel also displaying the values are correctly.
But my problem is, after export to excel, when i change the Qty or Rate columns in excel file the Amount is not get changed automatically, because the formula is missing in the excel cell.
How can we include the formula in Amount column while export to excel from .rdlc?
I'm afraid that this required behaviour isn't really possible by just using the rdlc rendering.
In my search I stumbled upon this same link that QHarr posted: https://social.msdn.microsoft.com/Forums/en-US/3ddf11bf-e10f-4a3e-bd6a-d666eacb5ce4/report-viewer-export-ms-report-data-to-excel-with-formula?forum=vsreportcontrols
I haven't tried the project that they're suggesting but this might possibly be your best solution if it works. Unfortunately I do not have the time to test it myself, so if you test this please share your results.
I thought of the following workaround that seems to work most of the times, but isn't really that reliable because the formula sometimes gets displayed as full-text instead of being calculated. But I guess this could be solved by editing the excel file just after being exported, and changing the cell properties of this column containing the formula or just triggering the calculate.
Using the built-in-field Globals!RenderFormat.Name you can determine the render mode, this way you can display the result correctly when the report is being rendered to something different than Excel. When you export to Excel, you could change the value of the cell to the actual formula.
To form the formula it's self you'll need to figure this out on your own, but the RowNumber(Scope as String) function can be of use here to determine the row number of your cells.
Here is a possible example for the expression value of your amount column
=IIF(Globals!RenderFormat.Name LIKE "EXCEL*", "=E" & Cstr(RowNumber("DataSet1")+2) & "*F" & Cstr(RowNumber("DataSet1")+2) ,Fields!Rate.Value * Fields!Qty.Value )
Now considering that this formula sometimes gets displayed as full-text, and you'll probably have to edit the file post-rendering. If it's too complicated to determine which row/column the cell is on, you could also do this post-rendering. But I believe that the above expression should be easy enough to use to get your desired result without having to do much after rendering.
Update: The following code could be used to force the calculation of the formula (post rendering)
var fpath = #"C:\MyReport.xlsx";
using (var fs = File.Create(fpath))
{
var lr = new LocalReport();
//Initializing your reporter
lr.ReportEmbeddedResource = "MyReport.rdlc";
//Rendering to excel
var fbytes = lr.Render("Excel");
fs.Write(fbytes, 0, fbytes.Length);
}
var xlApp = new Microsoft.Office.Interop.Excel.Application() { Visible = false };
var wb = xlApp.Workbooks.Open(fpath);
var ws = wb.Worksheets[1];
var range = ws.UsedRange;
foreach (var cell in range.Cells)
{
var cellv = cell.Text as string;
if (!string.IsNullOrWhiteSpace(cellv) && cellv.StartsWith("="))
{
cell.Formula = cellv;
}
}
wb.Save();
wb.Close(0);
xlApp.Quit();
While I'm trying to open excel file a message box is prompting like "We found a problem with some content in file name. Do you want us to try to recover as much as we can? If you trust the source of this workbook, click Yes.". What actually done is i have a excel template designed and copying the file to another file and created temp file I'm inserting data to temp file using OPEN XML and data is getting from the database.
i have tried the solutions provided in the net but those fixes are not resolving my issue.My excel is 2010
Anyone solution provided is much appreciated.
I had this problem. It was caused by the way I was storing numbers and strings in cells.
Numbers can be stored simply using cell.CellValue = new CellValue("5"), but for non-numeric text, you need to insert the string in the SharedStringTable element and get the index of that string. Then change the data type of the cell to SharedString, and set the value of the cell to the index of the string in the SharedStringTable.
// Here is the text I want to add.
string text = "Non-numeric text.";
// Find the SharedStringTable element and append my text to it.
var sharedStringTable = document.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First().SharedStringTable;
var item = sharedStringTable.AppendChild(new SharedStringItem(new Text(text)));
// Set the data type of the cell to SharedString.
cell.DataType = new EnumValue<CellValues>(CellValues.SharedString);
// Set the value of the cell to the index of the SharedStringItem.
cell.CellValue = new CellValue(item.ElementsBefore().Count().ToString());
This is explained in the documentation here: http://msdn.microsoft.com/en-us/library/office/cc861607.aspx
Another few cases that can cause this type of error:
Your sheet name is longer than 31 characters
You have invalid characters in sheet name
You have cells with values longer than 32k
The issue is due to using
package.Save();
and
package.GetAsByteArray();
at the same time
when we call
package.GetAsByteArray();
it will do following operations
this.Workbook.Save();
this._package.Close();
this._package.Save(this._stream);
Hence, removing
package.Save();
will solve this problem "We found a problem with some content in file name. Do you want us to try to recover as much as we can? If you trust the source of this workbook, click Yes."
Another possible cause could be exceeded maximum number of cell styles.
You can define:
up to 4000 styles in a .xls workbook
up to 64000 styles in a .xlsx workbook
In this case you should re-use the same cell style for multiple cells, instead of creating a new cell style for every cell.
I added the right cellReference and fixed this issue for me:
string alpha = "ABCDEFGHIJKLMNOPQRSTUVQXYZ";
for (int colInx = 0; colInx < reader.FieldCount; colInx++)
{
AppendTextCell(alpha[colInx] + "1", reader.GetName(colInx), headerRow);
}
private static void AppendTextCell(string cellReference, string cellStringValue, Row excelRow)
{
// Add a new Excel Cell to our Row
Cell cell = new Cell() { CellReference = cellReference, DataType = new EnumValue<CellValues>(CellValues.String) };
CellValue cellValue = new CellValue();
cellValue.Text = cellStringValue.ToString();
cell.Append(cellValue);
excelRow.Append(cell);
}
Same warning but the problem with me was that I was using a client input (name of wave) as sheet name for the file and when date was presented within the name, the character '/' used as date part separator was causing the issue.
I think Microsoft need to provide a better error log to save people time investigate such minor issues. Hope my answer will save someone else's time.
The issue was due to storing a string in the cell directly using cell.CellValue = new CellValue("Text"). It is possible to store numbers like this but not string. For string, define data type as string before assigning the text using Cell.DataType = CellValues.String;