Node - exceljs: writing to file breaks fomulas in the file - node.js

I have an excel (xlsx) file that contains random columns. Some of these columns have formulas mapped to the sum of some cells; for example:
=J8+F9-H9
In my case I have the following three columns:
F: number
H: number
J: =sum of previous row's F and H cell's values.
I aim to get external data and store them cell by cell in this workbook. For this I am using Node module exceljs.
This is my code so far, I am harcoding values for now (which I will be getting from another file later on).
var workbook = new Excel.Workbook();
var filename = 'Bank Synoptic Journal.xlsx'
workbook
.xlsx
.readFile(filename)
.then(function() {
var worksheet = workbook.getWorksheet('Bank Synoptic');
var row = null;
row = worksheet.getRow(8);
row.getCell('J').value = Math.random();
row.commit();
for(var i=9; i<=305;i++) { //row
row = worksheet.getRow(i);
row.getCell('F').value = Math.random();
row.getCell('H').value = Math.random();
row.commit();
}
})
.then(function() {
return workbook.xlsx.writeFile(filename + '_modified.xlsx');
})
.then(function() {
console.log('Done!');
});
It prints the output into a new excel file. The problem I am facing is that for cells 'J' ie which contains the formulas; these cells are breaking with no consitency:
Some cells keep formulas and do the calculations
Others have no more formulas nor calculations done (have '0' instead of formula)
Recalculations are not done automatically using this injection mechanism
(Snapshots)
What I am missing or doing wrong that is leading to this error?

After several trials and errors I moved to Apache POI and so built the script using Java.
I downloaded and included the following JARs in my project:
It manipulates rows/columns and keeps the formulas intact. Once you open the modified excel file all you have to do is refresh (On Windows: ctrl + alt + f9) and it will recalculate.

Related

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 remove all the spaces in the cells of excelsheet using nodejs code

I have an excel sheet with lots of spaces in between the content in each cell. I would like to keep that cell unaffected, so I would like to create a copy of the same and remove all the spaces of cell content. Is it possible to do from a nodejs code?
You could do so using xlsx package from npm.
copy the File via node
const fs = require('fs');
fs.copyFile('source.xlsx', 'newFile.xlsx', (err) => {
if (err) throw err;
});
read the File to any Format you like with xlsx (code simplified):
XLSX = require('xlsx');
workbook = XLSX.read('newFile.xlsx', {type: 'binary'});
let worksheet = workbook.Sheets[workbook.SheetNames[0]];
initialData = XLSX.utils.sheet_to_json(worksheet);
console.log('initialData ')
now you have the first worksheet of your copied file as JSON and can perform whatever changes you like.
After using eg trim on every object you can write that JSON back to an Excel File
let workbook1 = XLSX.utils.book_new();
let worksheet1 = XLSX.utils.json_to_sheet();
XLSX.utils.book_append_sheet(workbook1, worksheet1, 'WorksheetName');
XLSX.writeFile(workbook1, 'newFile.xlsx');
The first step is optional as you are only working inside the JSON copy an writing a new file afterwards, but I mentioned it as it was in the original question.
If you meant to remove the leading and the trailing white spaces, then this function should trim the white spaces from the header and all cells.
Please test it thoroughly before using it for production:
function trim_cells(ws) {
var range = XLSX.utils.decode_range(ws["!ref"]);
for (var R = range.s.r; R <= range.e.r; ++R) {
for (var C = range.s.c; C <= range.e.c; ++C) {
var coord = XLSX.utils.encode_cell({ r: R, c: C }),
cell = ws[coord];
if (!cell || !cell.v) continue;
// clean up raw value of string cells
if (cell.t == "s") cell.v = cell.v.trim();
// clean up formatted text
if (cell.w) cell.w = cell.w.trim();
}
}
}
Note - The above solution is found in the GitHub issue.
For more information on how to pass an excel worksheet (passed as a parameter) to the above function please look at the official GitHub link.

How to edit specific excel sheet

I have a maser sheet containing multiple sheets. I want to editing DATA sheet shown in the image and I can edit but when i edit the DATA sheet then the data and pivot tables and styling and formatting in Main repot and pivot sheets gets blank . how to stop being formatting and styling gets blank.
I am using laravel with maatwebiste.
below is the originalsheet
but when i store and download the updated sheet the sheet gets blank
this is data sheet
Excel::selectSheetsByIndex(2)->load($final_file_path, function($reader) {
$reader->sheet('Data', function($sheet) {
$select_arrays = ['85213','Age','40-49','2019-12-01','111111','Not Stated','Not Stated'];
$sheet->appendRow($select_arrays);
}, 'UTF-8')->store('xlsx', storage_path('/'), true);
Above code is working fine but when store to the path all formatting pivots are removed
Earlier I was using maatwebiste that does not support Pivot but now in my solution I used COM library used for excel.
Converting excel to pdf using PHP
The solution for the above problem mentioned below:-
// WORKBOOK AND WORKSHEET OBJECTS
$wbk = $xlapp->Workbooks->Open("C:\\xampp\htdocs\php-excel1\PivotReportMockUp.xlsx");
$wks = $wbk->Worksheets(2);
$wks1 = $wbk->Worksheets(1);
// SET CELL VALUE
$wks->Range("B2")->Value = "85552";
$wbk->save();
// OUTPUT WORKSHEET TO PDF
$xlTypePDF = 0;
$xlQualityStandard = 0;
$OpenAfterPublish= True; //`enter code here`
$IgnorePrintAreas = True;
try {
$wks1->ExportAsFixedFormat($xlTypePDF, "C:\\xampp\htdocs\php-excel1\PivotReport.pdf", $xlQualityStandard,$OpenAfterPublish,$IgnorePrintAreas);
} catch(com_exception $e) {
echo $e->getMessage()."\n";
exit;
}

PHPExcel prevent calculating formula

I'm trying to convert a CSV file to a XLSX file using PHPExcel library. Once the csv file is read into PHPExcel object and before saving it as a xlsx file, I recalculate and set column widths based on relevant column content.
$objReader = PHPExcel_IOFactory::createReader('CSV');
$objPHPExcel = $objReader->load("test.csv");
$activesheet = $objPHPExcel->getActiveSheet();
$lastColumn = $activesheet->getHighestColumn(); // get last column with data
$lastColumn++;
for ($column = 'A'; $column != $lastColumn; $column++) { // for each column until last
$activesheet->getColumnDimension($column)->setAutoSize(true); // set autowidth
}
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
$objWriter->save("downloads/test.xls");
with bit of a research i found that if there are any formulas in the file, call to setAutoSize() calculates the value for them to make use when calculating the column width.
My problem is that some of my csv files contain values that begins with = (equal sign) which are not formulas. for ex. cell values like '===='. This causes above code to throw an error PHPExcel_Calculation_Exception Formula Error: An unexpected error occured.
Since I know that any of my input csv files cannot contain formulas, is there a way to prevent PHPExcel calculating values for cells which contain values beginning with = sign?
After research and given suggestions I ended up iterating through all the cells and rewriting cell values (beginning with = sign), to prevent PHPExcel considering them as formulas. setCellValueExplicit() method instructs PHPExcel to not consider the cell value as a formula in this case.
foreach ($objPHPExcel->getWorksheetIterator() as $worksheet) {
foreach ($worksheet->getRowIterator() as $row) {
$cellIterator = $row->getCellIterator();
$cellIterator->setIterateOnlyExistingCells(true);
foreach ($cellIterator as $cell) {
if (preg_match( '/^=/', $cell->getValue())) {
$cellcoordinate = $cell->getCoordinate();
$worksheet->setCellValueExplicit($cellcoordinate,$worksheet->getCell($cellcoordinate));
}
}
}
}
It's painful, but couldn't find a better solution.

Compare values from one excel workbook to another

I have two excel workbooks. Workbook1 has list of urls and other i.e. Workbook2 has along with list of urls few more columns.
Workbook1:
COLUMN A
url_list
url1
url2
url3
url
Workbook2:
COLUMN A COLUMN B COLUMN C
Key Words URL Jan 2015
Website search Engine Optimisation url1 72614
Website search Engine Optimisation url2 20890
Website search Engine Optimisation url3 133968
Engine Optimisation url7 584625
I want to compare list of urls from workbook1(Column A) with workbook2(Column B).
If any url from workbook1 is missing in workbook2 then it has to be added in workbook2 in the end.
For example:
Now url is not present in workbook2, so it will be add , and will look like this
Workbook2:
COLUMN A COLUMN B COLUMN C
Key Words URL Jan 2015
Website search Engine Optimisation url1 72614
Website search Engine Optimisation url2 20890
Website search Engine Optimisation url3 133968
Engine Optimisation url7 584625
url
I am using library phpexcel to work with excel sheets in php in windows 7.
Also is there any direct excel formula to do so?
I know with php i can do this.
Thanks
I have a similar task and i have been working tirelessly compiling some code. Though no comparison in-built functions exist, i get data from two different workbooks here (.xlsx files), retrieve specific columns from two worksheets, strip off unnecessary stuff from the data, and store the values in two different associative arrays. I then can use in-built php functions to compare the arrays. You can then pick out the values you intend to write to a new worksheet. I still have to do more work pertaining to my task but i hope this helps someone some day.
<?php
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);
date_default_timezone_set('Europe/London');
define('EOL',(PHP_SAPI == 'cli') ? PHP_EOL : '<br />');
/** Include PHPExcel */
require_once dirname(__FILE__) . '/../Classes/PHPExcel.php';
//set_include_path(get_include_path() . PATH_SEPARATOR . '../../../Classes/');
//include_once 'Lib/PHPExcel.php';
$fileType = 'Excel2007';
$fileName = 'testBook.xlsx';
// Create new PHPExcel object
echo date('H:i:s') , " Create new PHPExcel object" , EOL;
$objPHPExcel = new PHPExcel();
$objPHPExcelXX = new PHPExcel();
$objPHPExcelW = new PHPExcel();
// Read the file
$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$objReaderXX = PHPExcel_IOFactory::createReader($fileType);
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcelW, 'Excel2007');
$objReader->setReadDataOnly(true);
$objReaderXX->setReadDataOnly(true);
try {
$objPHPExcel = $objReader->load("Gemeinde_Bad_Rothenfelde.xlsx");
$objPHPExcelXX = $objReaderXX->load($fileName);
$objWorksheet = $objPHPExcel->getActiveSheet();
$objWorksheetXX = $objPHPExcelXX->getActiveSheet();
print($objWorksheet->getTitle());
print($objWorksheetXX->getTitle());
//$objColumn = $objWorksheet->getHighestColumn();
//$objOtherCols = $objWorksheet->getHighestColumn();
$highestRow = $objWorksheetXX->getHighestRow();
$gemendeHighest = $objWorksheet->getHighestRow();
}catch(Exception $e) {
die($e->getMessage());
}
print("\n");
$arrayOrtStr = array();
$arrayGemStr = array();
$count = 1;
$i = 0;
//$colOrtXX is column in primus sheet, $colOrts is column in Gemeinde sheet,the numbers are the real column numbers in the sheets
for ($row = 1, $colOrtXX=1, $colOrtsT=7, $colOrtsTeil=2,$colStrXX=3, $colOrt=6,$colStr = 10; $row <= $highestRow; $row++) {
//$cell = $objWorksheet->getCell($objColumn.$row);
//Getting cell values for Primus Sheet (Columns PostOrt,PostOrtsteil,PostStrasse)
$cellOrtXX = $objWorksheetXX->getCellByColumnAndRow($colOrtXX,$row);
$cellStrXX = $objWorksheetXX->getCellByColumnAndRow($colStrXX,$row)->setDataType(PHPExcel_Cell_DataType::TYPE_STRING);
$cellOrtsTeil = $objWorksheetXX->getCellByColumnAndRow($colOrtsTeil,$row);
$valOrtXX = $cellOrtXX->getValue();
$valStrXX = $cellStrXX->getValue();
$valOrtsTeil = $cellOrtsTeil->getValue();
// Get cell values for Gemeinde sheet (Columns Ort and Strasse)
$cellOrt = $objWorksheet->getCellByColumnAndRow($colOrt,$row);
$cellStr = $objWorksheet->getCellByColumnAndRow($colStr,$row)->setDataType(PHPExcel_Cell_DataType::TYPE_STRING);
//$cellOrtsT = $objWorksheet->getCellByColumnAndRow($colOrtsT,$row);
$valOrt = $cellOrt->getValue();
$valStr = $cellStr->getValue();
// array populated for strasse column in gemeinde sheet but numbers stripped off the address
$onlyStr = preg_replace('/[0-9]+/','',$valStr);
$arrayGemStr[$i] = array("Strasse"=>$onlyStr);
// Go through the Strasse column, only pick cells with Ort Bad Rothenfelde..compare and write
if($valOrtXX == "Bad Rothenfelde"){
// Creating associative array with Ortsteil and Strasse from Primus sheet
$arrayOrtStr[$i] = array("OrtsTeil"=>$valOrtsTeil,"Strasse"=>$valStrXX);
}
$i++;
//print_r($array);
}
$ortTeil = array();
$contentFound = array();
$withStr = array();
foreach($arrayOrtStr as $arr) {
$contentFound[] = $arr['Strasse'];
}
foreach($arrayOrtStr as $arr) {
if(in_array($arr['Strasse'], $contentFound)){
$ortTeil[] = $arr["OrtsTeil"];
$withStr[] = $arr["Strasse"];
}
}
echo '<br/>========================================================<br/>';
print_r($ortTeil);
print_r($withStr);
// Write the Excel file to filename some_excel_file.xlsx in the current directory
//$objWriter = new PHPExcel_Writer_Excel2007($objPHPExcelW);
//$objWriter->save('Gemeinde_Bad_.xlsx');
Copy ColumnA (excluding header/s) from Workbook1 and append to ColumnB of Workbook2 then apply Excel's Remove Duplicates to ColumnB of Workbook2. Removing duplicates should delete all entries from your example but you might blank out B2 (or maybe B1) from Workbook2 first to avoid that.
I post here a very simple method.
This is not a "direct formula", but it may work for you.
I will assume your sources are Sheet1 and Sheet2 in the same workbook, it is easy to adapt to your needs.
Steps to follow:
Add a helper column in Sheet1:
Enter formula =IF(ISNA(MATCH($A2,Sheet2!$B$2:$B$5,0)),ROW(),100000) in B2.
Copy downwards. This will extract the row numbers of URLs to be copied, using a number larger than those for the rest (100000 here). Replace Sheet2!$B$2:$B$5 by the actual range.
Set a list of indexes N of URLs to copy: Locate in Sheet2 the cell at the row just below the last (6 in your example) and the column just to the right of the last (D in your case). Enter the sequence 1,2,... from that cell down.
Pick the Nth URL to copy: Enter the formula =OFFSET(Sheet1!$A$2,SMALL(Sheet1!$B:$B,D6)-2,0) in B6. Copy down.
Variations on this can be produced.
We are migrating from PHPExcel to PhpSpreadsheet. Here is the snippet I used in my phpunit test to compare 2 excel files using PhpSpreadsheet:
// compare files
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
// no need to read styles, we just care about data
$reader->setReadDataOnly(true);
// load expected file (stored somewhere in the tests directory)
$spreadsheetExpected = $reader->load($expectedFilePath);
// load the generated file
$spreadsheetActual = $reader->load($actualFilePath);
// loop through 3 pages, indices 0, 1, and 2
foreach (range(0, 2) as $sheet) {
// loop through 2 rows
foreach (range(1, 20) as $row) {
// loop through first 6 columns
foreach (['A', 'B', 'C', 'D', 'E', 'F'] as $column) {
// find coordination
$cell = $column . $row;
// get expected cell value
$expected = $spreadsheetExpected->getSheet($sheet)->getCell($cell)->getValue();
// get actual cell value
$actual = $spreadsheetActual->getSheet($sheet)->getCell($cell)->getValue();
// compare values, show the sheet and coordination in case of failure
$this->assertEquals($expected, $actual, "Mismatch in sheet {$sheet}, cell {$cell}");
}
}
}
Apparently this test fails on the first mismatch.

Resources