Apache-poi how to unhide column upon creation of Excel file - apache-poi

I am trying to generate an Excel workbook which will be a template.
For now I am trying to generate a workbook with 1 sheet that holds only header cells with values, with certain Height and Width values. The problem is not that I cannot do it, but when I generate/create the .xlsx file the cells are hidden in a certain way and I have to click N(if there are 13 cells) times to display them all.
[Example of how Cells are hidden]
[1]: https://i.stack.imgur.com/xYh1P.png
And the way I want them to be displayed upon creation of the file is like this.
[Example of how I wish them to be displayed uppon creation]
[2]: https://i.stack.imgur.com/FWILw.png
The code is as follows
//creating workbook
private static void createWorkBookFile() throws IOException {
String filePath = "C:\\UltimateMapper\\UltimateMapperProject\\";
filePath+="\\WriteTestFiles";
System.out.print("Enter name of file: ");
String fileName = scan.nextLine();
filePath+="\\"+fileName+".xlsx";
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet currentSheet = workbook.createSheet("File to STG");
XSSFRow row;
XSSFCell cell;
//TO DO START FORM HERE FINISH AND THEN INSIDE LOOP
String[] fileToSTGCellValues_Names = new String[] {"Source Location_Schema","Source File_Table Name",
"Source_Field_Column Name","Start Pos","End Pos",
"Source Field Length","Source Field_Column Data Type",
"Transformation","Target Location_Schema","Target File_Table Name",
"Target Field_Column Name","Target Field_Column Data Type","Comments"};
HashMap<String,Integer> fileToSTGCellValues_Widths = new HashMap<String,Integer>();
fileToSTGCellValues_Widths.put("Source Location_Schema",26);
fileToSTGCellValues_Widths.put("Source File_Table Name",26);
fileToSTGCellValues_Widths.put("Source_Field_Column Name",35);
fileToSTGCellValues_Widths.put("Start Pos",10);
fileToSTGCellValues_Widths.put("End Pos",10);
fileToSTGCellValues_Widths.put("Source Field Length",18);
fileToSTGCellValues_Widths.put("Source Field_Column Data Type",21);
fileToSTGCellValues_Widths.put("Transformation",43);
fileToSTGCellValues_Widths.put("Target Location_Schema",18);
fileToSTGCellValues_Widths.put("Target File_Table Name",36);
fileToSTGCellValues_Widths.put("Target Field_Column Name",36);
fileToSTGCellValues_Widths.put("Target Field_Column Data Type",20);
fileToSTGCellValues_Widths.put("Comments",47);
int headeRowNumber = 0;
row = currentSheet.createRow(headeRowNumber);
row.setHeightInPoints(28.50f);
for(int i =0;i<13;i++) {
currentSheet.setColumnWidth(i, fileToSTGCellValues_Widths.get(fileToSTGCellValues_Names[i]));
cell = row.createCell(i);
cell.setCellValue(fileToSTGCellValues_Names[i]);
}
FileOutputStream fout = new FileOutputStream(filePath);
workbook.write(fout);
fout.close();
System.out.println("File created");
}```

Related

Finding difficulty to add one more sheet in Excel workbook using Apache POI

My following 3 line code is used to create one file with sheet1(Year 2019) now would like to execute another page and need to store the result of it in same file as sheet2(Year 2020).
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sheet = wb.createSheet("Year 2019");
FileOutputStream fos = new FileOutputStream("C:\\Users\\dp\\Desktop\\MData1_Test_1.xlsx");
Row header_1 = sheet.createRow(rowNum[0]);
rowNum[0] = (rowNum[0] + 1);
header_1.createCell(0).setCellValue("Analytics");
Any help will be appreciated.
You can do something like this:
// open your first file
try (InputStream inp = new FileInputStream(fut.get())) {
Workbook wb = WorkbookFactory.create(inp);
// get sheet by name
Sheet sheet = wb.getSheet("Year 2019");
if (null != sheet) {
// if sheet exists => delete it
int index = wb.getSheetIndex(String name);
wb.removeSheetAt(index);
}
// create new sheet
sheet = wb.createSheet("Year 2019");
// proceed adding data
// row = sheet.createRow(0);
// row.createCell(0).setCellValue("data");
// ...
}
You can repeat these steps as many time as you need to manage as many sheets as you want.

How to fix "The supplied data appears to be in the Office 2007+ XML."

This is my code that extracts value from an xlsx file and print it on Eclipse console
public class testcode {
public void readexcel(String filepath, String filename, String sheetname) throws IOException
{
//Create an object of file class to open xlsx file
File file = new File(filepath+"\\"+filename);
//Create an object of FileInputStream to read an xlsx file
FileInputStream inputstream = new FileInputStream(file);
Workbook workbook = null;
//Find file extension name by using substring
String FileExtensionName = filename.substring(filename.indexOf("."));
//Check condition whether file is xlsx or xls
if(FileExtensionName.equalsIgnoreCase("xlsx"))
workbook = new XSSFWorkbook(inputstream);
else
workbook = new HSSFWorkbook(inputstream);
//Read sheet inside the workbook by its name
Sheet sheet = workbook.getSheet(sheetname);
//Find number of rows in sheet
int rowCount = sheet.getLastRowNum() - sheet.getFirstRowNum();
//Create a loop over all the rows of excel file to read it
for(int i = 0; i<rowCount+1;i++)
{
Row row = sheet.getRow(i);
//Create loop to print cell values in a row
for(int j = 0; j<row.getLastCellNum();j++)
{
//Print excel value in console System.out.println(row.getCell(j).getStringCellValue()+"||");
}
System.out.println();
}
}
public static void main(String[] args) throws IOException {
testcode objExcelFile = new testcode();
//Prepare path of excel file
String filepath = "C:\\Users\\malfoy\\Desktop";
objExcelFile.readexcel(filepath,"testfile.xlsx", "read");
}
}
I am using office 2007 edition and I am getting an exception which says
"The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)"
How to fix it?
The line
String FileExtensionName = filename.substring(filename.indexOf("."));
returns a value with the dot (in your case ".xlsx")
So the following if statement returns a HSSFWorkbook instance instead of XSSFWorkbook.
To correct it use
String FileExtensionName = filename.substring(filename.lastIndexOf(".")+1);

Reading images from all excel worksheets using Apache POI

I am trying to copy all the images from all the worksheets from an existing excel file to a new excel file. For this, I read all the sheets from the existing excel file and copy the images to the new excel file. The following code accesses all the sheets and tries to copy all the images to the new sheet.
public static void modifyExcelFile(XSSFWorkbook xssfWorkbook) throws InvalidFormatException, IOException, XmlException{
String newFileName = "outputexcelfile.xlsx";
XSSFWorkbook dest = new XSSFWorkbook("test.xlsx");
int numSheets = xssfWorkbook.getNumberOfSheets();
// clone the template sheet additional number of times required
for(int i=1; i<numSheets; i++){
dest.cloneSheet(0);
}
for(int i=0; i<numSheets; i++) {
XSSFSheet destSheet = dest.getSheetAt(i);
dest.setSheetName(i, xssfWorkbook.getSheetName(i));
XSSFSheet sheet = xssfWorkbook.getSheetAt(i);
// copy images
System.out.println("Copying images ...");
copyImages(sheet, destSheet);
}
writeFile(dest, newFileName);
}
test.xlsx is the template file with only one sheet. The following copyImages function tries to copy all the images from one sheet to the other.
public static void copyImages(XSSFSheet from, XSSFSheet to) throws IOException, XmlException, InvalidFormatException{
Drawing drawingPatriarch = to.createDrawingPatriarch();
XSSFWorkbook destWorkbook = to.getWorkbook();
// Add image
for (POIXMLDocumentPart pdp : from.getRelations()) {
if (!XSSFRelation.DRAWINGS.getRelation().equals(pdp.getPackageRelationship().getRelationshipType())) continue;
PackagePart drawPP = pdp.getPackagePart();
WsDrDocument draw = WsDrDocument.Factory.parse(drawPP.getInputStream());
for (CTTwoCellAnchor twoAnc : draw.getWsDr().getTwoCellAnchorList()) {
String picId = twoAnc.getPic().getBlipFill().getBlip().getEmbed();
PackageRelationship pr = drawPP.getRelationship(picId);
PackagePart imgPP = drawPP.getRelatedPart(pr);
System.out.println(imgPP.getPartName() + ": contentType: " + imgPP.getContentType() + " size: " + imgPP.getSize()
+ ": picId: " + picId
+" - Col1: "+twoAnc.getFrom().getCol()
+" - Row1: "+twoAnc.getFrom().getRow()
+" - Col2: "+twoAnc.getTo().getCol()
+" - Row2: "+twoAnc.getTo().getRow()
);
// skip the logo
if(twoAnc.getFrom().getCol()==0 && twoAnc.getFrom().getRow()==0)
continue;
try {
InputStream is = imgPP.getInputStream();
byte[] bytes = IOUtils.toByteArray(is);
int pictureIdx = destWorkbook.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
is.close();
CreationHelper helper = destWorkbook.getCreationHelper();
//add a picture shape
ClientAnchor anchor = helper.createClientAnchor();
//set top-left corner of the picture,
anchor.setCol1(twoAnc.getFrom().getCol());
anchor.setRow1(twoAnc.getFrom().getRow());
anchor.setRow2(twoAnc.getTo().getRow());
anchor.setCol2(twoAnc.getTo().getCol());
Picture pict = drawingPatriarch.createPicture(anchor, pictureIdx);
}catch(IOException ioEx){
System.out.println("Failed to add icons. Details: " + ioEx.getMessage());
}
}
}
}
But if I run the code, it only copies images from the first sheet successfully. For all other sheets, images are not there. The code runs successfully without any errors. Any help is greatly appreciated. Thanks!
Just adding pict.resize(); function call after the Picture pict=... fixes the issue. So the modified code looks like the following:
Picture pict = drawingPatriarch.createPicture(anchor, pictureIdx);
pict.resize();
Not sure why it doesn't work without the resize() call.

dropdown Validation not working if it exceeds 50 rows in the Export To Excel

I am generating Excel File(.xlsx) using apache poi jar (poi-ooxml-3.9.jar), I added dropdown validation for 10 columns in my excel file, If I generate the Excel File with 50 rows, drop down validation is working. If it exceeds more than 50 rows, drop down validation is not coming in the Excel File, When I open the excel File I get the message as "We found a problem with some content in fileName.xlsx. Do you want us to try to recover as much as we can ? If you trust the source of this workbook, click Yes ". when click on Yes, all the dropdown validation it is removing. Kindly need solution to fix this issue.
Do not create DataValidationConstraint for each single cell but only for each varying list you need. Then create DataValidation using those DataValidationConstraint for continuous CellRangeAddressList which are as big as possible and also are not all single cells.
Example creates ten different list validations for column 1 to 10 in rows 1 to 10000.
import java.io.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
class DataValidationList {
public static void main(String[] args) throws Exception {
Workbook workbook = new XSSFWorkbook(); // or new HSSFWorkbook
Sheet sheet = workbook.createSheet("Data Validation");
DataValidationHelper dvHelper = sheet.getDataValidationHelper();
for (int col = 0; col < 10; col++) {
DataValidationConstraint dvConstraint = dvHelper.createExplicitListConstraint(
new String[]{"Col "+(col+1)+" one","Col "+(col+1)+" two","Col "+(col+1)+" three"});
CellRangeAddressList addressList = new CellRangeAddressList(0, 9999, 0, col);
DataValidation validation = dvHelper.createValidation(
dvConstraint, addressList);
if(validation instanceof XSSFDataValidation) {
validation.setSuppressDropDownArrow(true);
validation.setShowErrorBox(true);
}
else {
validation.setSuppressDropDownArrow(false);
}
sheet.addValidationData(validation);
}
String filename;
if(workbook instanceof XSSFWorkbook) {
filename = "DataValidationList.xlsx";
} else {
filename = "DataValidationList.xls";
}
FileOutputStream out = new FileOutputStream(filename);
workbook.write(out);
out.close();
workbook.close();
}
}

How to set formula have table column field in Apache POI

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();
}
}

Resources