使用 Apache POI 3.9 ,我想将一些值映射到类似于此的Excel模板:
看起来非常简单,至少对于 卖方 表,我可以毫无问题地映射我的bean中的值。
但是,我面临的问题与 Products 表有关,因为我需要为每个列设置我的bean数据,这使逻辑变得有点因为在循环过程中我需要查找下一个列字母:
例如 我的第一个产品数据将设置在 B7 下,然后设置在 C7,D7,E7等直到循环结束。
(只是要知道,对于这个示例模板,我只是展示了产品的“Name”属性,但每个人在现实生活中都有大约35个属性,这就是为什么我没有在行中显示数据,因为在水平视图中,用户对用户看起来不那么友好。)
所以,我的问题是:
如果我的产品数量超过了 字母表,如何在循环过程中获得正确的列和单元格 在Excel列分发后设置我的产品bean数据?
使用“Excel列分发”我的意思如下:
例如 在Excel中,当转到包含字母“Z”的最后一个字母的列时,列继续显示< em> AA,AB,AC等。
这是我尝试过的(使用虚拟数据),这将一直有效,直到进入“Z”列的字母:
此代码段中使用的空Excel模板可在以下位置下载: https://www.dropbox.com/s/eo0s54o9vkqhlbl/template.xls
package com.app.test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellReference;
/**
* Test class for generating Excel sheet
*/
public class ExportTest
{
public static void main(String[] args) throws IOException
{
CellReference ref;
// Load template
InputStream fis = ExportTest.class.getResourceAsStream("/template.xls");
Workbook workbook = new HSSFWorkbook(fis);
fis.close();
// Constants
final String TBL_FIRSTCOLUMN = "B"; // Starting product table column at sheet (in which the first product data will be set)
final int MAX_PRODUCTS = 25; // Max. products added to the dummy products list (this will set the last product to the "Z" column)
final int TBL_STARTROW = 7; // Starting product table row number at sheet (in which the first product data will be set)
final int TBL_ATTR_ROWS = 1; // Number of attribute rows at products table (in this case just "Name")
// Generate dummy data with seller information
LinkedHashMap<String, String> cellMap = new LinkedHashMap<String, String>();
cellMap.put("B2", "1");
cellMap.put("B3", "Company");
cellMap.put("B4", "US");
// Generate dummy data with product information
List<String> products = new ArrayList<String>();
for(int i = 0; i < MAX_PRODUCTS; ++i) {
products.add("Chocolate");
}
// Declare style for cells
CellStyle style = workbook.createCellStyle();
style.setBorderLeft(CellStyle.BORDER_THIN);
style.setLeftBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderRight(CellStyle.BORDER_THIN);
style.setRightBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderTop(CellStyle.BORDER_THIN);
style.setTopBorderColor(IndexedColors.BLACK.getIndex());
style.setBorderBottom(CellStyle.BORDER_THIN);
style.setBottomBorderColor(IndexedColors.BLACK.getIndex());
// Get template sheet
Sheet sheet = workbook.getSheetAt(0);
// Set values to "Seller" table
for(Map.Entry<String, String> entry : cellMap.entrySet()) {
ref = new CellReference(entry.getKey());
sheet.getRow(ref.getRow()).getCell(ref.getCol()).setCellValue(entry.getValue());
}
// Set values to "Products" table
for(int i = 0; i < products.size(); ++i) {
// Get product name
String name = products.get(i);
String num = String.valueOf(i + 1);
// Get char representation of the letter, this will allow me to get
// C, D, E...Z columns but then I will get a IllegalArgumentException
// if my products count exceed the alphabet letters. At this point I'll
// need to follow Excel column distribution behavior.
String nextLetter = String.valueOf((char)(TBL_FIRSTCOLUMN.charAt(0) + i));
for(int j = 0; j < TBL_ATTR_ROWS; ++j) {
// Get cell reference of B7 then C7, etc
ref = new CellReference(nextLetter + (TBL_STARTROW + j));
// Check if row/cell exists, otherwise it will throw NullPointerException when trying to get each one
Row row = sheet.getRow(ref.getRow());
if(row == null) {
row = sheet.createRow(ref.getRow());
}
Cell cell = row.getCell(ref.getCol());
if(cell == null) {
cell = row.createCell(ref.getCol());
}
// Set value and style to cell
cell.setCellValue(name + num);
cell.setCellStyle(style);
}
}
// Write workbook to file
String path = String.format("%s%s%s", System.getProperty("user.home"), System.getProperty("file.separator"), "exported.xls");
OutputStream out = new FileOutputStream(new File(path));
workbook.write(out);
out.close();
}
}
然后,如果产品数量超过字母,我将得到以下例外:
线程“main”中的异常java.lang.IllegalArgumentException:无效 列索引(-11)。 BIFF8的允许列范围为(0..255)或 ('A'..'IV')at org.apache.poi.hssf.usermodel.HSSFCell.checkBounds(HSSFCell.java:939) 在org.apache.poi.hssf.usermodel.HSSFCell。(HSSFCell.java:153) 在org.apache.poi.hssf.usermodel.HSSFRow.createCell(HSSFRow.java:148) 在org.apache.poi.hssf.usermodel.HSSFRow.createCell(HSSFRow.java:126) 在org.apache.poi.hssf.usermodel.HSSFRow.createCell(HSSFRow.java:39) 在 com.app.test.ExportTest.main(ExportTest.java:99)
(要使用MAX_PRODUCTS = 26
复制此尝试,不 27 - 字母数量 - 因为我们从Excel工作表上的B列开始)。
任何帮助将不胜感激,谢谢!
答案 0 :(得分:2)
您在Apache POI中调用实用程序方法 - CellReference.convertNumToColString
将您的列号映射到Excel列名称。
接受基于0的base-10列并返回ALPHA-26表示。例如,列#3 - &gt; d
因为您从列&#34; B&#34;开始(1
),首先将1
添加到i
。
String nextLetter = String.valueOf(CellReference.convertNumToColString(i + 1));