my code is looking like:
public void Main() throws IOException {
XSSFWorkbook wb = new XSSFWorkbook();
IDataTable tempTable = bundle.getDataTable(ObjectName);
XSSFSheet wsh = wb.createSheet(TabName);
saveCsvIntoWsh(tempTable, wb, wsh);
public void saveCsvIntoWsh(IDataTable tempTable, XSSFWorkbook wb, XSSFSheet wsh) {
int rowNumber = tempTable.getTableRows().size();
int colNumber = tempTable.getColumnCount();
int cellRef;
//check if there is only 1 row to include header
if (rowNumber == 1) {
cellRef = rowNumber;
} else{
cellRef = rowNumber-1;
}
//set up table size, 0,0 is A1, row size is starting from A2 (1) plus sizer
AreaReference reference = wb.getCreationHelper().createAreaReference(new
CellReference(0, 0), new CellReference(cellRef, colNumber - 1));
XSSFTable myTable = wsh.createTable(reference);
List <String []> str = tempTable.getDataRows();
System.out.println(str.get(0));
//get table and add table style
CTTable cttable = myTable.getCTTable();
CTTableStyleInfo tableStyle = cttable.addNewTableStyleInfo();
tableStyle.setName("TableStyleMedium14");
cttable.setDisplayName(wsh.getSheetName());
}
How to set up format for entire column in table?
I saw that there is method for setting up the cell but the issue is related to whole column, not only cell.
Please help,
MichaĆ
I have an excel which has multiple sheet. Now I want to get row count for each sheet
var XLSX = require('xlsx');
var workbook = XLSX.readFile('test.xlsx');
var sheet_name_list = workbook.SheetNames;
let count = [];
for (var sheetIndex = 0; sheetIndex < sheet_name_list.length; sheetIndex++) {
var worksheet = workbook.Sheets[sheet_name_list[sheetIndex]];
var range = XLSX.utils.decode_range(worksheet['!ref']);
var num_rows = range.e.r - range.s.r + 1;
count.push({
data_count: num_rows
});
}
return count;
By using above script I am getting maximum 65536 even though excel has 100000 record.
try changing:
var range = XLSX.utils.decode_range(worksheet['!ref']);
to:
var range = XLSX.utils.decode_range(worksheet['!fullref']);
I have a huge data that needs to be written to excel from database in chunks using OpenXML.
I read a set of data ( 1000 rows) from database and write to excel for the first time. I loop and read the second set of data ( next 1000 rows) and have to append it to the existing excel rows.
using (SpreadsheetDocument spreadSheet = SpreadsheetDocument.Open(destination, true))
{
WorkbookPart workbookPart = spreadSheet.WorkbookPart;
IEnumerable<Sheet> sheets = spreadSheet.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>();
string relationshipId = sheets.FirstOrDefault(s => string.Compare(s.Name, "Sheet 1", true) == 0).Id;
WorksheetPart worksheetPart = (WorksheetPart)spreadSheet.WorkbookPart.GetPartById(relationshipId);
SheetData sheetData = new SheetData();
DocumentFormat.OpenXml.Spreadsheet.Row headerRow = new DocumentFormat.OpenXml.Spreadsheet.Row();
List<String> columns = new List<string>();
System.Data.DataTable dt = ds.Tables[0];
foreach (DataColumn column in dt.Columns)
{
columns.Add(column.ColumnName);
DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(column.ColumnName);
headerRow.AppendChild(cell);
}
sheetData.AppendChild(headerRow);
foreach (DataRow dsrow in dt.Rows)
{
DocumentFormat.OpenXml.Spreadsheet.Row newRow = new DocumentFormat.OpenXml.Spreadsheet.Row();
foreach (String col in columns)
{
DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(dsrow[col].ToString());
newRow.AppendChild(cell);
}
sheetData.AppendChild(newRow);
}
worksheetPart.Worksheet.ReplaceChild<SheetData>(sheetData, worksheetPart.Worksheet.Elements<SheetData>().FirstOrDefault());
I'm not sure how of you do it on SpreadSheetDocument by Microsoft, I have used a more simpler 3rd party DLL which uses SpreadSheetDocument and has minimized the programmer's work.
Anyhow, if you know the specific row index from where the next set of data should be written from, say 1002 in your case (1000 rows and 1 row of header). (Supposedly save in a Session variable or dynamically get the start index by knowing how many rows of data has been written in the excel sheet)
I think you could do something like,
int rowIndex = 1002; //This you derive
DocumentFormat.OpenXml.Spreadsheet.Row newRow = new DocumentFormat.OpenXml.Spreadsheet.Row() { RowIndex = rowIndex };
Note:
The { RowIndex = rowIndex } should be considered only in the first instance of the loop when you begin appending.
Hope this helps.
I'm using OpenXML in my ASP.NET application. Here is the code for generating it:
MemoryStream ms = new System.IO.MemoryStream();
SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(ms, SpreadsheetDocumentType.Workbook);
WorkbookPart workbookPart = spreadsheetDocument.AddWorkbookPart();
workbookPart.Workbook = new Workbook();
WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet();
UInt32Value rowIndex = 0;
SheetData sheetData = new SheetData();
Row r1 = new Row() { RowIndex = rowIndex };
Cell c1 = new Cell() { DataType = CellValues.String, CellValue=new CellValue("col1") };
Cell c2 = new Cell() { DataType = CellValues.String, CellValue = new CellValue("col2") };
Cell c3 = new Cell() { DataType = CellValues.String, CellValue = new CellValue("col3") };
Cell c4 = new Cell() { DataType = CellValues.String, CellValue = new CellValue("col4") };
r1.Append(new List<Cell>() { c1, c2, c3, c4 });
rowIndex++;
sheetData.Append(r1);
foreach (Rezultat rez in rezultati)
{
Row r2 = new Row() { RowIndex = rowIndex };
Cell c1 = new Cell() { DataType = CellValues.String, CellValue = new CellValue(rez.a) };
Cell c2 = new Cell() { DataType = CellValues.String, CellValue = new CellValue(rez.b) };
Cell c3 = new Cell() { DataType = CellValues.String, CellValue = new CellValue(rez.c) };
Cell prolaz = new Cell() { DataType = CellValues.String };
if (rez.d)
{
prolaz.CellValue = new CellValue("DA");
}
else
{
prolaz.CellValue = new CellValue("NE");
}
r2.Append(new List<Cell>() { c1,c2,c3,c4 });
rowIndex++;
sheetData.Append(r2);
}
worksheetPart.Worksheet.Append(sheetData);
Sheets sheets = new Sheets();
Sheet sheet = new Sheet();
sheet.Name = "first";
sheet.SheetId = 1;
sheet.Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart);
sheets.Append(sheet);
spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(sheets);
spreadsheetDocument.WorkbookPart.Workbook.Save();
spreadsheetDocument.Close();
string fileName = "testOpenXml.xlsx";
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", string.Format("attachment; filename={0}", fileName));
ms.WriteTo(Response.OutputStream);
ms.Close();
Response.End();
When I download it, and try to open it in excel, I got message that excel found unreadable context in excel.I suppose I have to change the way how I geenrate excel. I tried couple of solutions, some gave same error and some open excel, but with no data in it.
You will get this error if the cells do not appear in order in the file.
If you are using Microsoft's Sample Code in "How to: Insert text into a cell in a spreadsheet document (Open XML SDK)" in DevCenter you will see there is a function called InsertCellInWorksheet. This function has the defective line in it:
if (string.Compare(cell.CellReference.Value, cellReference, true) > 0)
If you have more than 26 columns, this will cause them to be sorted like this:
A1 AA1 AB1 B1 C1 D1 E1 ....
The result is you will see the data in column A and from AA on. Columns B through Z will be missing and you will get the dreaded "Excel found unreadable content" message.
You need to replace this string.Compare with a function that will put AA1 after Z1, or... if you know you are creating everything in order change it to if (false).
What you want to create are cells of type InlineString instead of String.
Below is a snippet to achieve part of what you need. Hopefully, you can modify it to your needs.
SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(#"test.xlsx", SpreadsheetDocumentType.Workbook);
WorkbookPart workbookPart = spreadsheetDocument.AddWorkbookPart();
WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
Row row = new Row { RowIndex = 1 };
Cell cell1 = new Cell { DataType = CellValues.InlineString };
InlineString inlineString1 = new InlineString();
Text text = new Text { Text = "col1" };
inlineString1.Append(text);
cell1.Append(inlineString1);
Cell cell2 = new Cell { DataType = CellValues.InlineString };
InlineString inlineString2 = new InlineString();
Text text2 = new Text { Text = "col2" };
inlineString2.Append(text2);
cell2.Append(inlineString2);
row.Append(new List<Cell>() { cell1, cell2 });
SheetData sheetData = new SheetData();
sheetData.Append(row);
Worksheet worksheet = new Worksheet();
worksheet.Append(sheetData);
worksheetPart.Worksheet = worksheet;
worksheetPart.Worksheet.Save();
Sheets sheets = new Sheets();
string relId = workbookPart.GetIdOfPart(worksheetPart);
Sheet sheet = new Sheet { Name = "Sheet1", SheetId = 1, Id = relId };
sheets.Append(sheet);
Workbook workbook = new Workbook();
workbook.Append(sheets);
spreadsheetDocument.WorkbookPart.Workbook = workbook;
spreadsheetDocument.WorkbookPart.Workbook.Save();
spreadsheetDocument.Close();
I know this is an old question, but I ran into this problem and found the solution in a MSDN forum. The SDK samples contain code that simply does not work with columns beyong Z (like AA for example).
As mentioned here, the problem is that using alphabetial order, AA1 will come before B1 and so on. The way to resolve it is to make the letters base-26 numbers. In the very same MSDN forum, the solution was given.
First create a base-26 converter:
//Hexavigesimal (Excel Column Name to Number) - Bijective
private int fromBase26(string colName)
{
colName = colName.ToUpper();
int decimalValue = 0;
for (int i = 0; i < colName.Length; i++)
{
decimalValue *= 26;
decimalValue += (colName[i] - 64);
}
return decimalValue;
}
Then, change this line in the method to insert a cell in the worsheet from:
if (string.Compare(cell.CellReference.Value, cellReference, true) > 0)
To:
if (fromBase26(Regex.Replace(cell.CellReference.Value, #"[\d-]", string.Empty)) > fromBase26(Regex.Replace(cellReference, #"[\d-]", string.Empty)))
I need to delete certain rows from an excel file. The excel file is a template and may have extra rows, which have to be deleted for the final output. However deletion of the cells corrupts the file. The code is as simple as follows
Worksheet worksheet = worksheetPart.Worksheet;
SheetData sheetData = worksheet.GetFirstChild<SheetData>();
foreach (var row in sheetData.Elements<Row>().
Where(r => r.RowIndex.Value >= rowIndex && r.RowIndex.Value < rowIndex + count).ToList())
{
row.Remove();
}
Alternatively, I tried setting the existing cells to blank values.
Worksheet worksheet = worksheetPart.Worksheet;
SheetData sheetData = worksheet.GetFirstChild<SheetData>();
foreach (var row in sheetData.Elements<Row>().
Where(r => r.RowIndex.Value >= rowIndex && r.RowIndex.Value < rowIndex + count).ToList())
{
IEnumerable<Cell> cells = row.Elements<Cell>().ToList();
if (cells != null)
{
foreach (Cell cell in cells)
{
if (cell.CellValue != null && !String.IsNullOrEmpty(cell.CellValue.Text))
{
cell.DataType = new EnumValue<CellValues>(CellValues.String);
cell.CellValue = new CellValue("");
}
}
}
}
My file always gets corrupted.
The issue was that the final streams to save the worksheet/workbooks, had a mismatch in the sizes.