【问题标题】:jExcelApi - cell date format reusing doesn't workjExcelApi - 单元格日期格式重用不起作用
【发布时间】:2009-09-22 15:07:19
【问题描述】:

我为 jExcelApi 类创建了一个包装器,以便轻松地将对象列表导出到 Excel。为了最大限度地减少对象创建,单元格格式被创建为静态字段,并在连续调用导出时重复使用。但是我遇到了日期格式的问题——第一次调用效果很好,但是在所有连续的导出中,日期单元格都有数字格式而不是日期格式。如果我为日期格式创建一个新对象而不是使用静态字段,那么一切都很好。对不同的工作表或工作簿使用相同的格式对象是否有任何原因会失败?
这是代码,简化了异常处理,省略了其他数据类型,可能缺少一些导入:

ExcelCellGenerator.java:

import jxl.write.WritableCell;

public interface ExcelCellGenerator<T> {
 WritableCell getCell(int col, int row, T arg);
}

ExcelCellGeneratorFactory.java:

import jxl.write.DateFormat;
import jxl.write.DateTime;
import jxl.write.Label;
import jxl.write.NumberFormat;
import jxl.write.NumberFormats;
import jxl.write.WritableCell;
import jxl.write.WritableCellFormat;
import ExcelExporter.DateTimeExtractor;

final class ExcelCellGeneratorFactory {
 private ExcelCellGeneratorFactory() {}

 private static final WritableCellFormat DATE_FORMAT = new WritableCellFormat ( new DateFormat ("dd MMM yyyy hh:mm:ss")); // reusing this field fails

 static public <T> ExcelCellGenerator<T> createDateCellGenerator(final DateTimeExtractor<T> extractor) {
  return new ExcelCellGenerator<T>() {
   public WritableCell getCell(int col, int row, T arg) {
    return new DateTime(col, row, extractor.extract(arg), DATE_FORMAT);
                // if there is new WritableCellFormat(new DateFormat(...)) instead of DATE_FORMAT, works fine
   }

  };
 }
}

ExcelExporter.java:

import jxl.Workbook;
import jxl.write.DateFormat;
import jxl.write.DateTime;
import jxl.write.Label;
import jxl.write.NumberFormat;
import jxl.write.WritableCellFormat;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;

public class ExcelExporter<T> {
 // describe a column in Excel sheet
 private static class ColumnDescription<T> {
  public ColumnDescription() {}

        // column title
        private String title;
        // a way to generate a value given an object to export
        private ExcelCellGenerator<T> generator;
 }

    // all columns for current sheet
 private List<ColumnDescription<T>> columnDescList = new ArrayList<ColumnDescription<T>>();

    // export given list to Excel (after configuring exporter using addColumn function
    // in row number rowStart starting with column colStart there will be column titles
    // and below, in each row, extracted values from each rowList element
 public byte[] exportList(int rowStart, int colStart, List<? extends T> rowList) {
  final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
  WritableWorkbook workbook;
  try {
   workbook = Workbook.createWorkbook(outputStream);
  } catch (IOException e) {
   e.printStackTrace();
  }
  final WritableSheet sheet = workbook.createSheet("Arkusz1", 0);

  int currRow = rowStart;
  try {
   int currCol = colStart;
   for (ColumnDescription<T> columnDesc : columnDescList) {
    final Label label = new Label(currCol, currRow, columnDesc.title);
    sheet.addCell(label);
    currCol++;
   }
   currRow++;

   for (T object : rowList) {
    currCol = colStart;
    for (ColumnDescription<T> columnDesc : columnDescList) {
     sheet.addCell(columnDesc.generator.getCell(currCol, currRow, object));
     currCol++;
    }
    currRow++;
   }

   workbook.write();
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   try {
    workbook.close();
   } catch (Exception e) {
    e.printStackTrace();
   }
  }

  return outputStream.toByteArray();
 }

    // configure a Date column
    public ExcelExporter<T> addColumn(String title, DateTimeExtractor<T> extractor) {
  final ColumnDescription<T> desc = new ColumnDescription<T>();
  desc.title = title;
  desc.generator = ExcelCellGeneratorFactory.createDateCellGenerator(extractor);
  columnDescList.add(desc);
  return this;
 }

    // and test that shows the problem
    public static void main(String []args) {
        final ExcelExporter<Date> exporter = new ExcelExporter<Date>();
        exporter.addColumn("Data", new DateTimeExtractor<Date>() {
            public Date extract(Date date) {
                return date;
        }});

        // this file looks OK
        FileOutputStream ostream = new FileOutputStream("C:\\tmp\\test1.xls");
        try {
            ostream.write(exporter.exportList(0, 0, Collections.singletonList(new Date())));
        } finally {
            ostream.close();
        }

        // but in this file date is shown in cell with numeric format
        final ExcelExporter<Date> exporter2 = new ExcelExporter<Date>();
        exporter2.addColumn("Data", new DateTimeExtractor<Date>() {
            public Date extract(Date date) {
                return date;
        }});

        ostream = new FileOutputStream("C:\\tmp\\test2.xls");
        try {
            ostream.write(exporter2.exportList(0, 0, Collections.singletonList(new Date())));
        } finally {
            ostream.close();
        }
    }
}

【问题讨论】:

    标签: java excel datetime jexcelapi


    【解决方案1】:

    Telcontar 的回答很有帮助,因为它说明它是一项功能,而不是错误,但还不够,因为没有提供任何指向常见问题解答或文档的链接。所以我做了一些研究,发现了一个FAQ,上面写着:

    另外,不要将单元格格式声明为静态也很重要。将单元格格式添加到工作表时,会为其分配一个内部索引号。

    所以答案是 - 格式不能在不同的工作表中重复使用,因为它们的设计目的不是以这种方式重复使用。

    【讨论】:

    • 实际上,只要它们在同一个工作簿中,它们就可以在不同的工作表中重复使用。
    【解决方案2】:

    jxl 格式的对象不能在多个工作簿中重复使用。我不知道为什么。

    【讨论】:

    • 如果您提供指向某些说明这一点的文档或常见问题解答的链接,我将很高兴接受您的回答。
    【解决方案3】:

    实际上比这更糟糕。字体和格式隐含地依赖于“工作簿”。哪个工作簿说明问题的问题。 他们似乎需要在创建后续工作簿后重新分配。

        final WritableWorkbook workbook = Workbook.createWorkbook(response
                .getOutputStream());
    
        // We have to assign this every time we create a new workbook.
        bodyText = new WritableCellFormat(WritableWorkbook.ARIAL_10_PT);
        ...
    

    应该更改 API,以便构造函数需要它们相关的工作簿作为参数,或者构造函数应该是私有的,并且应该从工作簿中获取字体和格式。

        WritableCellFormat bodyText = new WritableCellFormat(workbook,
                WritableWorkbook.ARIAL_10_PT);
    

        WritableCellFormat bodyText = workbook.getCellFormat(
                WritableWorkbook.ARIAL_10_PT);
    

    【讨论】:

      【解决方案4】:

      你可以试试SmartXLS,单元格格式可以在任何你想要的地方重复使用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-08
        相关资源
        最近更新 更多