首页 > 解决方案 > Apache POI:如何根据 Java DateTimeFormatter 设置单元格的 dataFormat

问题描述

我需要使用主机操作系统上指定的格式将日期和时间数据导出到 Excel。

我发现在 Java 中获得这种格式的唯一方法是使用 DateTimeFormatter。然后我需要使用 Apache POI 设置 Excel 单元格的数据格式。我怎么做?

要获取 CellStyle 中方法 setDataFormat 的数据格式,我必须有一个格式字符串(或表示内置类型的短字符串),但我无法从 DateTimeFormatter 中获取字符串模式。有没有办法进行这种转换?

final SXSSFWorkbook workbook;
final CellStyle style;
final DataFormat formatFactory;

style = workbook.createCellStyle();
DateTimeFormatter format = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT); //Format depends on local settings on client machine

style.setDataFormat(formatFactory.getFormat(format)); //Doesn't work

标签: javaexceldatetimeapache-poi

解决方案


可以使用java.text.DateFormat如下方式实现此要求:

DateFormat format = DateFormat.getDateTimeInstance(
                     DateFormat.SHORT, DateFormat.SHORT,
                     Locale.getDefault());
String pattern = ((SimpleDateFormat)format).toPattern();
System.out.println(pattern);

或者java.time.format.DateTimeFormatterBuilder像这样使用:

String pattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern(
                  FormatStyle.SHORT, FormatStyle.SHORT, 
                  Chronology.ofLocale(Locale.getDefault()),
                  Locale.getDefault());
System.out.println(pattern);

在这两种情况下,都需要转换模式以Excel使用DateFormatConverter,如下所示:

pattern = DateFormatConverter.convert(Locale.getDefault(), pattern);
System.out.println(pattern);

完整示例:

import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.DateFormatConverter;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.util.Date;
import java.util.Locale;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.FormatStyle;
import java.time.chrono.Chronology;

class CreateExcelCellDateFormat {

 public static void main(String[] args) throws Exception {

  //Locale.setDefault(new Locale("en", "US"));

  System.out.println(Locale.getDefault());

  String pattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern(
   FormatStyle.SHORT, FormatStyle.SHORT, 
   Chronology.ofLocale(Locale.getDefault()), Locale.getDefault());
  System.out.println(pattern);

/*
  DateFormat format = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.getDefault());
  String pattern = ((SimpleDateFormat)format).toPattern();
  System.out.println(pattern);
*/

  pattern = DateFormatConverter.convert(Locale.getDefault(), pattern);
  System.out.println(pattern);

  try (Workbook workbook = new XSSFWorkbook(); 
       FileOutputStream fileout = new FileOutputStream("Excel.xlsx") ) {

   CellStyle style = workbook.createCellStyle();
   style.setDataFormat(workbook.createDataFormat().getFormat(pattern));

   Sheet sheet = workbook.createSheet();
   Cell cell = sheet.createRow(0).createCell(0);
   cell.setCellStyle(style);
   cell.setCellValue(new Date());

   sheet.setColumnWidth(0, 25 * 256);

   workbook.write(fileout);
  }

 }
}

但是,如果真正的要求是创建一个Excel工作簿,该工作簿显示依赖于Excel 应用程序运行的用户区域设置的日期时间值,那么这一切都不是必需的。然后使用BuiltinFormats 0xe, "m/d/yy" 短日期或 0x16, "m/d/yy h:mm" 短日期时间。

例子:

import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

class CreateExcelCellDateFormatUserLocale {

 public static void main(String[] args) throws Exception {

  try (Workbook workbook = new XSSFWorkbook(); 
       FileOutputStream fileout = new FileOutputStream("Excel.xlsx") ) {

   CellStyle style = workbook.createCellStyle();
   //style.setDataFormat((short)14); //0xe, "m/d/yy"
   style.setDataFormat((short)22); //0x16, "m/d/yy h:mm"

   Sheet sheet = workbook.createSheet();
   Cell cell = sheet.createRow(0).createCell(0);
   cell.setCellStyle(style);
   cell.setCellValue(new java.util.Date());

   sheet.setColumnWidth(0, 25 * 256);

   workbook.write(fileout);
  }

 }
}

该代码会生成一个Excel文件,该文件显示的日期时间与应用程序Excel运行的语言环境完全一样。对于德国,它显示 dd.MM.yyyy hh:mm。对于美国,它显示 MM/dd/yy h:m AM/PM。对于英国,它显示 dd/MM/yyyy hh:mm。Excel


推荐阅读