I'm using npoi to save data in excel sheet,but i have a huge data it takes more than 1 hour when trying to insert data like that so i'm trying to insert data bulk into excel sheet.
public byte[] getWorkbook(DataTable dt)
{
IRow currentRow;
HSSFWorkbook workbook;
var worksheet = workbook.CreateSheet("Sheet1");
for(int i = 0; i < dt.Rows.Count; i++)
{
currentRow=worksheet.CreateRow(i);
for(int j = 0; j < dt.Columns.Count; j++)
{
currentRow.CreateCell(j).SetCellValue(dt.Rows[i][j].ToString());
worksheet.AutoSizeColumn(j);
}
}
var stream =new MemoryStream();
workbook.Write(stream);
return stream.ToArray();
}
Reading each value from DataTable and moving it cell by cell in excel is a usual way of transferring data. But for bulk data, this procedure is not recommended because of time complexity.
So to overcome this we can use clipboard to copy data from DataTable and we can paste it into the range of excel.It improves performance.
To achieve this, DataTable don't have default function to copy data to clipboard. So we have to convert Datatable to array and from array to sting. And string can be easily copied to clipboard and can be pasted in Excel.
Please find a link for reference here
Related
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
I created an XSSFTable with below example code:
https://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/xssf/usermodel/examples/CreateTable.java
One column in my XSSFTable is a formula that referencing to another column in this table.
For example, in XSSFTable TBL column ColumnA, the formula is: =[#[ColumnB]], I can set the formula on each cell in ColumnA via cell.setCellFormula("TBL[[#This Row],[ColumnB]]"), but it will have problem while opened in Excel and Excel has to remove the formula in order to display the worksheet correctly.
This problem only happened in creating blank new XSSFWorkbook, if it is loaded from an existing .xlsx file created by Excel, it is able to modify the formula via cell.setCellFormula() and able to open in Excel correctly.
If there are any sample code can work correctly in this situation?
Main problem with the linked example is that it names all columns equal "Column":
...
for(int i=0; i<3; i++) {
//Create column
column = columns.addNewTableColumn();
column.setName("Column");
column.setId(i+1);
...
So formula parser cannot difference between them.
But the whole logic of filling the table column headers and filling the sheet contents using one loop is not really comprehensible. So here is a more appropriate example:
public class CreateTable {
public static void main(String[] args) throws IOException {
Workbook wb = new XSSFWorkbook();
XSSFSheet sheet = (XSSFSheet) wb.createSheet();
//Create
XSSFTable table = sheet.createTable();
table.setDisplayName("Test");
CTTable cttable = table.getCTTable();
//Style configurations
CTTableStyleInfo style = cttable.addNewTableStyleInfo();
style.setName("TableStyleMedium2");
style.setShowColumnStripes(false);
style.setShowRowStripes(true);
//Set which area the table should be placed in
AreaReference reference = new AreaReference(new CellReference(0, 0),
new CellReference(4,2));
cttable.setRef(reference.formatAsString());
cttable.setId(1);
cttable.setName("Test");
cttable.setTotalsRowCount(1);
CTTableColumns columns = cttable.addNewTableColumns();
columns.setCount(3);
CTTableColumn column;
XSSFRow row;
XSSFCell cell;
//Create 3 columns in table
for(int i=0; i<3; i++) {
column = columns.addNewTableColumn();
column.setName("Column"+i);
column.setId(i+1);
}
//Create sheet contents
for(int i=0; i<5; i++) {//Create 5 rows
row = sheet.createRow(i);
for(int j=0; j<3; j++) {//Create 3 cells each row
cell = row.createCell(j);
if(i == 0) { //first row is for column headers
cell.setCellValue("Column"+j);
} else if(i<4){ //next rows except last row are data rows, last row is totals row so don't put something in
if (j<2) cell.setCellValue((i+1)*(j+1)); //two data columns
else cell.setCellFormula("Test[[#This Row],[Column0]]*Test[[#This Row],[Column1]]"); //one formula column
}
}
}
FileOutputStream fileOut = new FileOutputStream("ooxml-table.xlsx");
wb.write(fileOut);
fileOut.close();
wb.close();
}
}
i had a excel sheet which is coming to a jsp from the servlet. Can someone help me of how to write a jsp page to display the excel contents in the browser.
Thanks in advance.
If the excel is not changing the structure dynamically, I recommend you to build a set of objects and parse these information in the server, and then in the jsp read these objects to build an html table with this set of objects.
You can load an Excel file with the class HSSFWorkbook or XSSFWorkbook, and then loop to the rows and cells for building your objects.
Please have a look at the examples of Apache Poi here
You can do something like this...
if(sheet.getPhysicalNumberOfRows() > 0) {
lastRowNum = sheet.getLastRowNum();
for(int j = 0; j <= lastRowNum; j++) {
row = sheet.getRow(j);
lastCellNum = row.getLastCellNum();
for(int i = 0; i <= lastCellNum; i++) {
cell = row.getCell(i);
if(cell == null) {
csvLine.add("");
}
else { //set your properties here...
}
}
}
}
I have some Data to put them into an Excel sheet, 4 values, n rows. I tried this:
final HSSFWorkbook wb = new HSSFWorkbook();
final HSSFSheet sheet = wb.createSheet();
FileOutputStream stream;
HSSFRow row = null;
try {
stream = new FileOutputStream(targetDirectory + "workbook.xls");
for (int i = 1; i < data.size(); i++) {
row = sheet.createRow((short) i);
cell = row.createCell(0);
cell.setCellValue("Das");
cell = row.createCell(1);
cell.setCellValue("hier");
cell = row.createCell(2);
cell.setCellValue("soll");
cell = row.createCell(3);
cell.setCellValue("rein");
wb.write(stream);
}
stream.close();
} catch ...
While writing into the EXCEL file I can watch growing the size to 1.600 kB. When I open the sheet I see one row. Closing the file without saving decrease the size to 4 kB.
It seems as the rows where all there but invisible?
Any idea, what am I doing wrong?
I'm not sure why, but you seem to be writing the workbook out on every single row, always to the same file. That means you'll end up with multiple copies of the workbook in the same file, which isn't really what you wanted at all!
Move the wb.write call to the end, and it should all work just fine. Excel is a binary format, it's not like CSV, so you should only write the file out when you're finished
I have a complex object(tree structure) which I am flattening it out into a datatable to display it on an excel sheet. Datatable is huge and has around 20000 rows and 10000 columns.
Writing the data onto an excel cell one at a time took forever. So, I am converting the complex object into a datatable and then writing it to the excel sheet using the code below.
Is it possible to write 20K rows x 10K columns data to an excel sheet fairly quickly in less than a minute or < 5 minutes? What is the best technique to complete this task fast.
Environment: Visual studio 2010, VSTO excel workbook project, .net framework 4.0, excel 2010/2007
EDIT:
Original source of data is a rest service response in json format. I am then deserializing json response into c# objects and finally flattening it into a datatable.
Using this Code to write datatable to an excel sheet:
Excel.Range oRange;
var oSheet = Globals.Sheet3;
int rowCount = 1;
foreach (DataRow dr in resultsDataTable.Rows)
{
rowCount += 1;
for (int i = 1; i < resultsDataTable.Columns.Count + 1; i++)
{
// Add the header the first time through
if (rowCount == 2)
{
oSheet.Cells[1, i] = resultsDataTable.Columns[i - 1].ColumnName;
}
oSheet.Cells[rowCount, i] = dr[i - 1].ToString();
}
}
// Resize the columns
oRange = oSheet.get_Range(oSheet.Cells[1, 1],
oSheet.Cells[rowCount, resultsDataTable.Columns.Count]);
oRange.EntireColumn.AutoFit();
Final Solution:
Used a 2D Object array instead of datatable and wrote it to the range.
In addition to freezing Excel's animation, you can, given the data source this is coming from, save yourself the looping through the Excel.Range object, which is bound to be a bottleneck, by instead of writing to a Datatable, write to a string[,], which Excel can use to write to a Range at once. Looping through a string[,] is much faster than looping through Excel cells.
string[,] importString = new string[yourJsonSource.Rows.Count, yourJsonSource.Columns.Count];
//populate the string[,] however you can
for (int r = 0; r < yourJsonSource.Rows.Count; r++)
{
for (int c = 0; c < yourJsonSource.Columns.Count; c++)
{
importString[r, c] = yourJsonSource[r][c].ToString();
}
}
var oSheet = Globals.Sheet3;
Excel.Range oRange = oSheet.get_Range(oSheet.Cells[1, 1],
oSheet.Cells[yourJsonSource.Rows.Count, yourJsonSource.Columns.Count]);
oRange.Value = importString;
I can't speak about using a datatable for the job, but if you want to use Interop, you definitely want to avoid writing cell by cell. Instead, create a 2-d array, and write it at once to a range, which will give you a very significant performance improvement.
Another option you should consider is avoiding interop altogether, and using OpenXML. If you are working with Excel 2007 or above, this is typically a better approach to manipulate files.
VSTO is always gonna take its time, the best tip I can share with you is disable sheet refresh when you populate data, one way to do this is pop up a "Modal" progress dialog box and refresh your sheet in background, this will give you 50-70% better performance. Another thing you can do is update VS to sp1, it helps.