Ignite UI export to excel table with multi-column header - excel

I am using Ignite UI in my website to view the table and i need to export it to excel. I am using default Infragistricts functionality $.ig.GridExcelExporter.exportGrid, but i get table with only lower part of header. I have multi-column header, and i get only the lower part. Is there a way to fix it?

the igGridExcelExporter does not handle the MultiColumnHeaders. Also, the grid is exported into a table region inside the worksheet, which does not allow cell merging. This means that you can imitate a multi header by inserting a new row and merging cells in the exportEnding event:
exportEnding: function(sender, args) {
args.worksheet.rows().insert(0, 1); // insert one new row at index 0
//create a merged cells region that will act as a multi header
var mergedHeaderRegion = args.worksheet.mergedCellsRegions().add(0,1,0,2); // firstRowIndex, firstColumnIndex, lastRowIndex, lastColumnIndex
mergedHeaderRegion.value("Month1");
// style the newly inserted row as a header
for (var columnIndex = 0; columnIndex < 4; columnIndex++) {
args.worksheet.rows(0).getCellFormat(columnIndex).fill($.ig.excel.CellFill.createSolidFill("rgb(136, 136, 136)"));
args.worksheet.rows(0).getCellFormat(columnIndex).font().colorInfo(new $.ig.excel.WorkbookColorInfo("rgb(255, 255, 255)")); }
}
You can also refer to the following help topics and API docs:
http://www.igniteui.com/help/javascript-excel-library-merge-cells
http://help.infragistics.com/jQuery/2015.2/

Related

Excel office script - copy a row to a new tab if cell is NOT empty

I have created a script that will move an entire row to another tab on the worksheet if certain text is entered into a selected cell.
I want to be able to do this if the cell is not empty rather than having certain text and I would like the row to be deleted all except the first column.
The script is below and works really well, I'm not great at coding and managed to cobble this together from some other scripts i found but i now can't manage to edit it to fit this new task.
I tried using Javascript not equals signs and other symbols and can remove rows that are empty but i can't seem to make it work.
function main(workbook: ExcelScript.Workbook) {
// You can change these names to match the data in your workbook.
const TARGET_TABLE_NAME = 'TableNAdded';
const SOURCE_TABLE_NAME = 'TableN';
// Select what will be moved between tables.
const FILTER_COLUMN_INDEX = 27;
const FILTER_VALUE = 'Y';
// Get the Table objects.
let targetTable = workbook.getTable(TARGET_TABLE_NAME);
let sourceTable = workbook.getTable(SOURCE_TABLE_NAME);
// If either table is missing, report that information and stop the script.
if (!targetTable || !sourceTable) {
console.log(`Tables missing - Check to make sure both source (${TARGET_TABLE_NAME}) and target table (${SOURCE_TABLE_NAME}) are present before running the script. `);
return;
}
// Save the filter criteria currently on the source table.
const originalTableFilters = {};
// For each table column, collect the filter criteria on that column.
sourceTable.getColumns().forEach((column) => {
let originalColumnFilter = column.getFilter().getCriteria();
if (originalColumnFilter) {
originalTableFilters[column.getName()] = originalColumnFilter;
}
});
// Get all the data from the table.
const sourceRange = sourceTable.getRangeBetweenHeaderAndTotal();
const dataRows: (number | string | boolean)[][] = sourceTable.getRangeBetweenHeaderAndTotal().getValues();
// Create variables to hold the rows to be moved and their addresses.
let rowsToMoveValues: (number | string | boolean)[][] = [];
let rowAddressToRemove: string[] = [];
// Get the data values from the source table.
for (let i = 0; i < dataRows.length; i++) {
if (dataRows[i][FILTER_COLUMN_INDEX] === FILTER_VALUE) {
rowsToMoveValues.push(dataRows[i]);
// Get the intersection between table address and the entire row where we found the match. This provides the address of the range to remove.
let address = sourceRange.getIntersection(sourceRange.getCell(i, 0).getEntireRow()).getAddress();
rowAddressToRemove.push(address);
}
}
// If there are no data rows to process, end the script.
if (rowsToMoveValues.length < 1) {
console.log('No rows selected from the source table match the filter criteria.');
return;
}
console.log(`Adding ${rowsToMoveValues.length} rows to target table.`);
// Insert rows at the end of target table.
targetTable.addRows(-1, rowsToMoveValues)
// Remove the rows from the source table.
const sheet = sourceTable.getWorksheet();
// Remove all filters before removing rows.
sourceTable.getAutoFilter().clearCriteria();
// Important: Remove the rows starting at the bottom of the table.
// Otherwise, the lower rows change position before they are deleted.
console.log(`Removing ${rowAddressToRemove.length} rows from the source table.`);
rowAddressToRemove.reverse().forEach((address) => {
sheet.getRange(address).delete(ExcelScript.DeleteShiftDirection.up);
});
// Reapply the original filters.
Object.keys(originalTableFilters).forEach((columnName) => {
sourceTable.getColumnByName(columnName).getFilter().apply(originalTableFilters[columnName]);
});
}
If I understand your question correctly, you are currently filtering the table if the value = "Y" (the value assigned to FILTER_VALUE). This part is happening here:
if (dataRows[i][FILTER_COLUMN_INDEX] === FILTER_VALUE) {
You'd like to update this line from checking if the cell value is Y to checking if the cell value is not empty. To do this, you can update this line like so:
if (dataRows[i][FILTER_COLUMN_INDEX] as string !== "") {

Tabulator: add class to class list, on cells when hidden by pagination

I need to add and/or remove a class to all cells even when they are hidden by pagination. I am able to add a class, but only the cells on the active page are getting the class. I understand that is because it is only updating what is available in the DOM and the hidden rows are not active in the DOM at the time, I'm adding the class.
Is there a way that Tabulator handles this?
As you can see from below i'm getting the rows (not shown) and then looping over the rows and attempting to update the cell classList.
for (var i = 0; i < rows.length; i++) {
if (rows[i] != this){
var row = rows[i],
cell = row.getCell(col),
cellElement = cell.getElement();
cellElement.classList.add('disable-cell');
console.log(cell);
}
}

How to keep table formatting when sorting table generated by PHPSpreadsheet?

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

Flutter - Convert data from firestore into Excel sheet

How to convert data from Firestore Into an Excel sheet on both Android app and flutter web?
Any response will be appreciated... thanks in advance!
Excel library for flutter
You can go through the documentation here.
Now as jay asked to explain in detail how you are gonna retrive the data and store it in the excel sheet,
First step,
var excel = Excel.createExcel(); //create an excel sheet
Sheet sheetObject = excel['SheetName']; //create an sheet object
Second step, commands to write in excel sheet,
where A is column id and 1 is row.
var cell = sheetObject.cell(CellIndex.indexByString("A1"));
cell.value = 8; // Insert value to selected cell;
Third step, getting data from firebase
QuerySnapshot _qs =
await _notificationRef.where('language', isEqualTo: selectedLang).get(); // Lets say I have some collection where I need to get some documents with specific language
//This loop will iterate in all of the documents in the collection
for (int i = 0; i < _qs.docs.length; i++) {
string data = _qs.docs[i].data()['names']; //Where name is the field value in the document and i is the index of the document.
}
});
Now if we combine second and third step
QuerySnapshot _qs =
await _notificationRef.where('language', isEqualTo: selectedLang).get();
for (int i = 0; i < _qs.docs.length; i++) {
var cell = sheetObject.cell(CellIndex.indexByString('A${i+1}')); //i+1 means when the loop iterates every time it will write values in new row, e.g A1, A2, ...
cell.value = _qs.docs[i].data()['names']; // Insert value to selected cell;
}
});
Once you are done with the data part you can save the file,
// Save the Changes in file
excel.encode().then((onValue) {
File(join("Path_to_destination/excel.xlsx"))
..createSync(recursive: true)
..writeAsBytesSync(onValue);
});
Once you are done with the saving you can choose any of the library to share your sheet to others,
Usually this libraries asks you to provide a file or file path
which you can easily provide using the last code block explained where I passed file path to join method

How can I resize an Excel Table using Gembox.Spreadsheet?

I'm replacing Excel Table contents in an existing workbook with new contents from C# code using Gembox.Spreadsheet. Sometimes the data has more rows than the existing table, sometimes it has fewer. To resize the table my first attempt has been to incrementally add or remove rows. However, this can be slow if the difference in the number of rows is quite large. Here's the code:
var workbook = ExcelFile.Load("workbook.xlsx");
var table = workbook.Sheets["Sheet1"].Tables["Table1"];
var lastWrittenRowIndex = 0;
for(var rowIndex = 0; rowIndex < data.Count; rowIndex++)
{
// If the table isn't big enough for this new row, add it
if (rowIndex == table.Rows.Count) table.Rows.Add();
// … Snipped code to add information in 'data' into 'table' …
lastWrittenRowIndex = rowIndex;
}
// All data written, now wipe out any unused rows
while (lastWrittenRowIndex + 1 < table.Rows.Count)
{
table.Rows.RemoveAt(table.Rows.Count - 1);
}
Adding a profiler shows that by far the slowest operation is table.Rows.Add(). I haven't yet profiled a situation where I need to remove the rows, but I anticipate the same.
I know how large my data is before writing, so how can I prepare the table to be of the correct size in a smaller operation? There are formulae and pivot tables referencing the table and I don't want to break them.
Try again with this latest version that was just released (Full version: 45.0.35.1010):
https://www.gemboxsoftware.com/spreadsheet/downloads/BugFixes.htm
It has a Table.Rows.Add overload method that takes count.
There are also similar ones for Insert and RemoveAt as well, see the following help page:
https://www.gemboxsoftware.com/spreadsheet/help/html/Methods_T_GemBox_Spreadsheet_Tables_TableRowCollection.htm
Last just as an FYI, you can additionally also set the following:
workbook.AutomaticFormulaUpdate = false;
This should improve the performances as well.
Note, setting this property to false also improves the performances of all ExcelWorksheet.Rows and ExcelWorksheet.Columns insert and remove methods.

Resources