Apache POI cell border
I'm trying to create a sheet using Apache POI as below, but could not able to get proper borders for each cell in my sheet. I have set the borders using cellStyle.setBorder_____() methods as below. Not sure where I am going wrong with this.
public Sheet createInstructionsSheet(Workbook workbook)
{
Sheet sheet = workbook.createSheet(Constants.INSTRUCTIONS_SHEET_NAME);
sheet.protectSheet("financials");
int rowNum = 3;
String headerCellColor = "F8CBAD";
byte[] headerCellColorByte = null;
try {
headerCellColorByte = Hex.decodeHex(headerCellColor);
} catch (DecoderException e) {
e.printStackTrace();
}
XSSFColor headerColor = new XSSFColor(headerCellColorByte, null);
String bufferCellColor = "808080";
byte[] bufferCellColorByte = null;
try {
bufferCellColorByte = Hex.decodeHex(bufferCellColor);
} catch (DecoderException e) {
e.printStackTrace();
}
XSSFColor bufferColor = new XSSFColor(bufferCellColorByte, null);
ArrayList<String> instructions = new ArrayList<>();
instructions.add("1. Instruction 1.");
instructions.add("2. Instruction 2");
instructions.add("3. Instruction 3");
instructions.add("4. Instruction 4.");
Font headerFont = workbook.createFont();
headerFont.setBold(true);
headerFont.setFontName("Arial");
headerFont.setFontHeightInPoints((short) 14);
headerFont.setUnderline(HSSFFont.U_SINGLE);
headerFont.setColor(IndexedColors.BLACK.getIndex());
Font instructionsCellFont = workbook.createFont();
instructionsCellFont.setBold(false);
instructionsCellFont.setFontName("Arial");
instructionsCellFont.setFontHeightInPoints((short) 9);
instructionsCellFont.setColor(IndexedColors.BLACK.getIndex());
XSSFCellStyle headerCellStyle = (XSSFCellStyle) workbook.createCellStyle();
headerCellStyle.setFont(headerFont);
headerCellStyle.setFillForegroundColor(headerColor);
headerCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
headerCellStyle.setAlignment(HorizontalAlignment.CENTER);
headerCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
headerCellStyle.setWrapText(true);
headerCellStyle.setBorderBottom(BorderStyle.THIN);
headerCellStyle.setBorderTop(BorderStyle.THIN);
headerCellStyle.setBorderRight(BorderStyle.THIN);
headerCellStyle.setBorderLeft(BorderStyle.THIN);
XSSFCellStyle bufferCellStyle = (XSSFCellStyle) workbook.createCellStyle();
bufferCellStyle.setFillForegroundColor(bufferColor);
bufferCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
bufferCellStyle.setBorderBottom(BorderStyle.THIN);
bufferCellStyle.setBorderTop(BorderStyle.THIN);
bufferCellStyle.setBorderRight(BorderStyle.THIN);
bufferCellStyle.setBorderLeft(BorderStyle.THIN);
CellStyle instructionsCellStyle = workbook.createCellStyle();
instructionsCellStyle.setFont(instructionsCellFont);
instructionsCellStyle.setVerticalAlignment(VerticalAlignment.BOTTOM);
instructionsCellStyle.setAlignment(HorizontalAlignment.LEFT);
instructionsCellStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex());
instructionsCellStyle.setRightBorderColor(IndexedColors.BLACK.getIndex());
instructionsCellStyle.setTopBorderColor(IndexedColors.BLACK.getIndex());
instructionsCellStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex());
Row headerRow = sheet.createRow(0);
Cell headerCell1 = headerRow.createCell((short) 0);
headerCell1.setCellStyle(headerCellStyle);
headerCell1.setCellValue("INSTRUCTIONS TO UPLOAD DATA");
CellRangeAddress instructionsHeaderCell = new CellRangeAddress(0, 1, 0, 19);
sheet.addMergedRegion(instructionsHeaderCell);
Row bufferRow = sheet.createRow(2);
Cell bufferCell = bufferRow.createCell((short) 0);
bufferCell.setCellStyle(bufferCellStyle);
CellRangeAddress bufferMergedCell = new CellRangeAddress(2, 2, 0, 19);
sheet.addMergedRegion(bufferMergedCell);
for(String instruct:instructions)
{
Row instructionRow = sheet.createRow(rowNum);
Cell instructionCell = instructionRow.createCell((short) 0);
instructionCell.setCellStyle(instructionsCellStyle);
instructionCell.setCellValue(instruct);
CellRangeAddress instructionsValueCell = new CellRangeAddress(rowNum, rowNum, 0, 19);
sheet.addMergedRegion(instructionsValueCell);
++rowNum;
}
return sheet;
}
Can someone please help?
I'm trying to create a sheet using Apache POI as below, but could not able to get proper borders for each cell in my sheet. I have set the borders using cellStyle.setBorder_____() methods as below. Not sure where I am going wrong with this.
Related
Code :
public String[][] getExcelData(String excellocation, String sheetName) {
try {
String dataSets[][] = null;
FileInputStream file = new FileInputStream(new File(excellocation));
// Create Workbook instance holding reference to .xlsx file
XSSFWorkbook workbook = new XSSFWorkbook(file);
// Get first/desired sheet from the workbook
XSSFSheet sheet = workbook.getSheet(sheetName);
// count number of active rows
int totalRow = sheet.getLastRowNum();
// count number of active columns in row
int totalColumn = sheet.getRow(0).getLastCellNum();
// Create array of rows and column
dataSets = new String[totalRow][totalColumn];
// Iterate through each rows one by one
Iterator<Row> rowIterator = sheet.iterator();
DataFormatter formatter = new DataFormatter();
int i = 0;
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
// For each row, iterate through all the columns
Iterator<Cell> cellIterator = row.cellIterator();
int j = 0;
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
if (cell.getStringCellValue().contains("TestCases")) {
break;
}
// Check the cell type and format accordingly
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC:
dataSets[i][j++] = cell.getStringCellValue();
System.out.println(cell.getStringCellValue());
break;
case Cell.CELL_TYPE_STRING:
dataSets[i][j++] = cell.getStringCellValue();
System.out.println(cell.getStringCellValue());
break;
}
}
System.out.println("");
}
file.close();
return dataSets;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) throws IOException {
String excellocation = "C:\\Users\\Sivaranjani Gopal\\Desktop\\siva.xlsx";
String sheetName = "testdata";
ExcelReaderpg excel = new ExcelReaderpg();
Object[][] data = excel.getExcelData(excellocation, sheetName);
}
Note :
1.My Query is the value of i is always said to be 0. so dataset[0][1] for 1st row
for second row it should be dataset [1][0] [1][1] and so on.
why does i value remain the same and i get the desired output.
Can some one explain the value of i and j implementation in the array
I had a requirement of reading a excel sheet and change the color of some specific cells.
using (SpreadsheetDocument spreadSheet = SpreadsheetDocument.Open(docName, true))
{
WorksheetPart wbPart = spreadSheet.WorkbookPart.WorksheetParts.FirstOrDefault();
Row row1 = getRow(1, wbPart);
foreach (Cell c2 in row1.Elements<Cell>())
{
if (c2.CellReference.Value == "G1")
{
AddbackgroundFormat(spreadSheet, c2, "56BEFB");
}
}
}
//Getting the row using row index
static Row getRow(uint rowIndex, WorksheetPart worksheetPart)
{
Worksheet worksheet = worksheetPart.Worksheet;
SheetData sheetData = worksheet.GetFirstChild<SheetData>();
Row row;
if (sheetData.Elements<Row>().Where(r => r.RowIndex == rowIndex).Count() != 0)
{
row = sheetData.Elements<Row>().Where(r => r.RowIndex == rowIndex).First();
}
else
{
row = new Row() { RowIndex = rowIndex };
sheetData.Append(row);
}
return row;
}
//Adding styles two cells using the color passed
static void AddbackgroundFormat(SpreadsheetDocument document, Cell c, string colorCode)
{
Fills fs = AddFill(document.WorkbookPart.WorkbookStylesPart.Stylesheet.Fills, colorCode);
AddCellFormat(document.WorkbookPart.WorkbookStylesPart.Stylesheet.CellFormats, document.WorkbookPart.WorkbookStylesPart.Stylesheet.Fills);
c.StyleIndex = (UInt32)(document.WorkbookPart.WorkbookStylesPart.Stylesheet.CellFormats.Elements<CellFormat>().Count() - 1);
}
static Fills AddFill(Fills fills1, string colorCode)
{
Fill fill1 = new Fill();
PatternFill patternFill1 = new PatternFill() { PatternType = PatternValues.Solid };
ForegroundColor foregroundColor1 = new ForegroundColor() { Rgb = colorCode };
//BackgroundColor backgroundColor1 = new BackgroundColor() { Indexed = (UInt32Value)64U };
patternFill1.Append(foregroundColor1);
// patternFill1.Append(backgroundColor1);
fill1.Append(patternFill1);
fills1.Append(fill1);
return fills1;
}
static void AddCellFormat(CellFormats cf, Fills fs)
{
CellFormat cellFormat2 = new CellFormat() { NumberFormatId = 0, FontId = 0, FillId = (UInt32)(fs.Elements<Fill>().Count() - 1), BorderId = 0, FormatId = 0, ApplyFill = true };
cf.Append(cellFormat2);
}
I am trying to append the data from multiple sheets in the same workbook and append them to the first sheet.
Here's what I have been able to accomplish:
void SomeMethod()
{
HSSFWorkbook hssfwb;
using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
hssfwb = new HSSFWorkbook(file);
}
var BaseSheet = workbook.GetSheetAt(0);
for (int i = 1; i < workbook.NumberOfSheets; i++)
{
AddRowsToBaseSheet(BaseSheet, workbook.GetSheetAt(i), workbook);
}
}
private void AddRowsToBaseSheet(ISheet BaseSheet, ISheet sheet, HSSFWorkbook workbook)
{
var temp = sheet.GetRowEnumerator();
while (temp.MoveNext())
{
HSSFRow sourceRow = (HSSFRow)temp.Current;
HSSFRow destinationRow = (HSSFRow)BaseSheet.CreateRow(BaseSheet.LastRowNum + 1);
CopyRow(workbook, sourceRow, destinationRow);
}
}
private void CopyRow(HSSFWorkbook workbook, IRow sourceRow, IRow destinationRow)
{
// Loop through source columns to add to new row
for (int i = 0; i < sourceRow.LastCellNum; i++)
{
// Grab a copy of the old/new cell
ICell oldCell = sourceRow.GetCell(i);
ICell newCell = destinationRow.CreateCell(i);
// If the old cell is null jump to next cell
if (oldCell == null)
{
newCell = null;
continue;
}
// Set the cell data type
newCell.SetCellType(oldCell.CellType);
// Set the cell data value
switch (oldCell.CellType)
{
case CellType.Blank:
newCell.SetCellValue(oldCell.StringCellValue);
break;
case CellType.Boolean:
newCell.SetCellValue(oldCell.BooleanCellValue);
break;
case CellType.Error:
newCell.SetCellErrorValue(oldCell.ErrorCellValue);
break;
case CellType.Formula:
newCell.SetCellFormula(oldCell.CellFormula);
break;
case CellType.Numeric:
newCell.SetCellValue(oldCell.NumericCellValue);
break;
case CellType.String:
newCell.SetCellValue(oldCell.RichStringCellValue);
break;
case CellType.Unknown:
newCell.SetCellValue(oldCell.StringCellValue);
break;
}
}
}
I might be doing a foolish mistake, or is there any other library for the same?
Converting into dataset wont work in this case as the columns are not related
I am trying to setcellvalue for xlsx file , Program works fine with no error , but while opening the xlsx file it throws an error saying Excel Found unreadable content
public boolean setCellData(String sheetName,String colName,int rowNum, String data){
try{
fis = new FileInputStream(path);
workbook = new XSSFWorkbook(path);
if(rowNum<=0)
return false;
int index = workbook.getSheetIndex(sheetName);
int colNum=-1;
if(index==-1)
return false;
sheet = workbook.getSheetAt(index);
row=sheet.getRow(0);
for(int i=0;i<row.getLastCellNum();i++){
//System.out.println(row.getCell(i).getStringCellValue().trim());
if(row.getCell(i).getStringCellValue().trim().equals(colName))
colNum=i;
}
if(colNum==-1)
return false;
sheet.autoSizeColumn(colNum);
row = sheet.getRow(rowNum-1);
if (row == null)
row = sheet.createRow(rowNum-1);
cell = row.getCell(colNum);
if (cell == null)
cell = row.createCell(colNum);
// cell style
//CellStyle cs = workbook.createCellStyle();
//cs.setWrapText(true);
//cell.setCellStyle(cs);
cell.setCellValue(data);
fileOut = new FileOutputStream(path);
workbook.write(fileOut);
fileOut.close();
}
catch(Exception e){
e.printStackTrace();
return false;
}
return true;
}
You have initialized FileInputStream, but not used that. Please replace
fis = new FileInputStream(path);
workbook = new XSSFWorkbook(path);
with
fis = new FileInputStream(path);
workbook = new XSSFWorkbook(fis);
this works on my end and not showing any error.
I've read a bunch of stuff on the web about how to get at cell data using the OpenXML API. But there's really not much out there that's particularly straightforward. Most seems to be about writing to SpreadsheetML, not reading... but even that doesn't help much.
I've got a spreadsheet that has a table in it. I know what the table name is, and I can find out what sheet it's on, and what columns are in the table. But I can't figure out how to get a collection of rows back that contain the data in the table.
I've got this to load the document and get a handle to the workbook:
SpreadsheetDocument document = SpreadsheetDocument.Open("file.xlsx", false);
WorkbookPart workbook = document.WorkbookPart;
I've got this to find the table/sheet:
Table table = null;
foreach (Sheet sheet in workbook.Workbook.GetFirstChild<Sheets>())
{
WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(sheet.Id);
foreach (TableDefinitionPart tableDefinitionPart in worksheetPart.TableDefinitionParts)
{
if (tableDefinitionPart.Table.DisplayName == this._tableName)
{
table = tableDefinitionPart.Table;
break;
}
}
}
And I can iterate over the columns in the table by foreaching over table.TableColumns.
To read an Excel 2007/2010 spreadsheet with OpenXML API is really easy. Somehow even simpler than using OleDB as we always did as quick & dirty solution. Moreover it's not just simple but verbose, I think to put all the code here isn't useful if it has to be commented and explained too so I'll write just a summary and I'll link a good article. Read this article on MSDN, it explain how to read XLSX documents in a very easy way.
Just to summarize you'll do this:
Open the SpreadsheetDocument with SpreadsheetDocument.Open.
Get the Sheet you need with a LINQ query from the WorkbookPart of the document.
Get (finally!) the WorksheetPart (the object you need) using the Id of the Sheet.
In code, stripping comments and error handling:
using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, false))
{
Sheet sheet = document.WorkbookPart.Workbook
.Descendants<Sheet>()
.Where(s => s.Name == sheetName)
.FirstOrDefault();
WorksheetPart sheetPart =
(WorksheetPart)(document.WorkbookPart.GetPartById(theSheet.Id));
}
Now (but inside the using!) what you have to do is just to read a cell value:
Cell cell = sheetPart.Worksheet.Descendants<Cell>().
Where(c => c.CellReference == addressName).FirstOrDefault();
If you have to enumerate the rows (and they are a lot) you have first to obtain a reference to the SheetData object:
SheetData sheetData = sheetPart.Worksheet.Elements<SheetData>().First();
Now you can ask for all the rows and cells:
foreach (Row row in sheetData.Elements<Row>())
{
foreach (Cell cell in row.Elements<Cell>())
{
string text = cell.CellValue.Text;
// Do something with the cell value
}
}
To simply enumerate a normal spreadsheet you can use Descendants<Row>() of the WorksheetPart object.
If you need more resources about OpenXML take a look at OpenXML Developer, it contains a lot of good tutorials.
There are probably many better ways to code this up, but I slapped this together because I needed it, so hopefully it will help some others.
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml.Packaging;
private static DataTable genericExcelTable(FileInfo fileName)
{
DataTable dataTable = new DataTable();
try
{
using (SpreadsheetDocument doc = SpreadsheetDocument.Open(fileName.FullName, false))
{
Workbook wkb = doc.WorkbookPart.Workbook;
Sheet wks = wkb.Descendants<Sheet>().FirstOrDefault();
SharedStringTable sst = wkb.WorkbookPart.SharedStringTablePart.SharedStringTable;
List<SharedStringItem> allSSI = sst.Descendants<SharedStringItem>().ToList<SharedStringItem>();
WorksheetPart wksp = (WorksheetPart)doc.WorkbookPart.GetPartById(wks.Id);
foreach (TableDefinitionPart tdp in wksp.TableDefinitionParts)
{
QueryTablePart qtp = tdp.QueryTableParts.FirstOrDefault<QueryTablePart>();
Table excelTable = tdp.Table;
int colcounter = 0;
foreach (TableColumn col in excelTable.TableColumns)
{
DataColumn dcol = dataTable.Columns.Add(col.Name);
dcol.SetOrdinal(colcounter);
colcounter++;
}
SheetData data = wksp.Worksheet.Elements<SheetData>().First();
foreach (DocumentFormat.OpenXml.Spreadsheet.Row row in data)
{
if (isInTable(row.Descendants<Cell>().FirstOrDefault(), excelTable.Reference, true))
{
int cellcount = 0;
DataRow dataRow = dataTable.NewRow();
foreach (Cell cell in row.Elements<Cell>())
{
if (cell.DataType != null && cell.DataType.InnerText == "s")
{
dataRow[cellcount] = allSSI[int.Parse(cell.CellValue.InnerText)].InnerText;
}
else
{
dataRow[cellcount] = cell.CellValue.Text;
}
cellcount++;
}
dataTable.Rows.Add(dataRow);
}
}
}
}
//do whatever you want with the DataTable
return dataTable;
}
catch (Exception ex)
{
//handle an error
return dataTable;
}
}
private static Tuple<int, int> returnCellReference(string cellRef)
{
int startIndex = cellRef.IndexOfAny("0123456789".ToCharArray());
string column = cellRef.Substring(0, startIndex);
int row = Int32.Parse(cellRef.Substring(startIndex));
return new Tuple<int,int>(TextToNumber(column), row);
}
private static int TextToNumber(string text)
{
return text
.Select(c => c - 'A' + 1)
.Aggregate((sum, next) => sum * 26 + next);
}
private static bool isInTable(Cell testCell, string tableRef, bool headerRow){
Tuple<int, int> cellRef = returnCellReference(testCell.CellReference.ToString());
if (tableRef.Contains(":"))
{
int header = 0;
if (headerRow)
{
header = 1;
}
string[] tableExtremes = tableRef.Split(':');
Tuple<int, int> startCell = returnCellReference(tableExtremes[0]);
Tuple<int, int> endCell = returnCellReference(tableExtremes[1]);
if (cellRef.Item1 >= startCell.Item1
&& cellRef.Item1 <= endCell.Item1
&& cellRef.Item2 >= startCell.Item2 + header
&& cellRef.Item2 <= endCell.Item2) { return true; }
else { return false; }
}
else if (cellRef.Equals(returnCellReference(tableRef)))
{
return true;
}
else
{
return false;
}
}