【问题标题】:How to format Excel Cell as Date in Apache POI as with the Format Painter operation in Excel如何在 Apache POI 中将 Excel 单元格格式化为日期,就像 Excel 中的格式刷操作一样
【发布时间】:2018-03-22 21:14:17
【问题描述】:

我对 Apache POI 很陌生,我想知道如何执行格式刷操作将单元格格式化为日期格式,每次我尝试复制单元格的日期格式时,在 POI 中,它只能给我数字,不知道如何保持日期格式?

    // Get source cell type and style
    CellType type_from = cell_from.getCellTypeEnum();
    CellStyle style_from = cell_from.getCellStyle();

    // Get source cell data format
    short df = style_from.getDataFormat();

    // Change dest cell cell type, set format on it
    cell_to.setCellType(type_from);
    CellStyle style_to = cell_to.getCellStyle();
    style_to.setDataFormat(df);
    cell_to.setCellStyle(style_to);

我需要更改一些其他样式,例如边框、背景颜色、斜体字体等。你能举一个例子:创建一个xlsx文件,将1A设置为数字(比如10),2A设置为文本(“10”)1B设置为日期(01/12/2018),2B设置为10000(只是一个数字),然后尝试将 2A 转为数字,字体为 16,单元格背景为绿色,将 2B 转为日期,格式与 1B 相同,但为斜体。

【问题讨论】:

  • 该代码看起来大致如我所料,它到底是什么不起作用?
  • @Gagravarr 目标单元格格式不能绘制为日期,但始终为数字
  • 您的单元格样式可能用完了吗?为什么不将源单元格中的相同样式应用到目标单元格?
  • @Gagravarr 抱歉,我不太明白。什么是单元格样式用完?
  • “单元格样式用完是什么意思?”:Too many different cell formats“当工作簿在 Excel 2003 中包含超过大约 4,000 种不同的单元格格式组合或在 Excel 2007 及更高版本中包含超过 64,000 种不同的组合时,就会出现此问题版本。”可能您正在使用XSSF,它允许大约。 64,000 种不同的单元格格式,但 public **short** getDataFormat() 甚至不能超过 32,767,因为这是 short 的最大值。

标签: java apache-poi


【解决方案1】:

正如评论中所说,仅使用您的代码 sn-p 无法重现该问题。这说明了为什么需要Minimal, Complete, and Verifiable examples

我怀疑以下几点:您在循环中使用了 sn-p,并多次更改相同的样式 style_to,并将不同的 style_from 作为源。这是可能的,因为多个单元格cell_to 可能共享相同的样式。

处理Excel 电子表格的单元格样式并不像人们想象的那么简单。单元格样式存储在工作簿级别,在现代Excel 版本中为limited 到 64,000 种独特的单元格格式/单元格样式。因此,必须小心创建新的单元格样式。至少不应尝试为每个单元格创建新的单元格样式。

Apache poi 提供CellUtil,它具有多种实用功能,可以更轻松地处理单元格和行。处理样式的各种方法允许您根据需要创建CellStyles。当您对单元格应用样式更改时,代码将尝试查看是否已经存在满足您需求的样式。如果没有,那么它将创建一个新样式。这是为了防止创建太多样式。到目前为止,缺少的是用于处理字体的相同实用程序功能。字体也属于工作簿级别,因此不应随意创建。

以下示例也提供了用于创建字体的实用函数。

它采用了您在上一条评论中描述的ExcelTest.xlsx,并进行了您在那里描述的更改。它还进行了一些额外的更改以显示实用程序功能的工作方式。

来源:

代码:

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

import org.apache.poi.ss.util.CellUtil;

import java.util.Map;
import java.util.HashMap;

public class ExcelSetCellStyleDataFormat {

 //method for getting current font from cell
 private static Font getFont(Cell cell) {
  Workbook wb = cell.getRow().getSheet().getWorkbook();
  CellStyle style = cell.getCellStyle();
  return wb.getFontAt(style.getFontIndex());
 }

 private enum FontProperty {
  BOLD, COLOR, FONTHEIGHT, FONTNAME, ITALIC, STRIKEOUT, TYPEOFFSET, UNDERLINE
 }

 //method for getting font having special settings additional to given source font
 private static Font getFont(Workbook wb, Font fontSrc, Map<FontProperty, Object> fontproperties) {
  boolean isBold = fontSrc.getBold();
  short color = fontSrc.getColor();
  short fontHeight = fontSrc.getFontHeight();
  String fontName = fontSrc.getFontName();
  boolean isItalic = fontSrc.getItalic();
  boolean isStrikeout = fontSrc.getStrikeout();
  short typeOffset = fontSrc.getTypeOffset();
  byte underline = fontSrc.getUnderline();

  for (FontProperty property : fontproperties.keySet()) {
   switch (property) {
    case BOLD:
     isBold = (boolean)fontproperties.get(property);
    break;
    case COLOR:
     color = (short)fontproperties.get(property);
    break;
    case FONTHEIGHT:
     fontHeight = (short)fontproperties.get(property);
    break;
    case FONTNAME:
     fontName = (String)fontproperties.get(property);
    break;
    case ITALIC:
     isItalic = (boolean)fontproperties.get(property);
    break;
    case STRIKEOUT:
     isStrikeout = (boolean)fontproperties.get(property);
    break;
    case TYPEOFFSET:
     typeOffset = (short)fontproperties.get(property);
    break;
    case UNDERLINE:
     underline = (byte)fontproperties.get(property);
    break;
   }
  }

  Font font = wb.findFont(isBold, color, fontHeight, fontName, isItalic, isStrikeout, typeOffset, underline);
  if (font == null) {
   font = wb.createFont();
   font.setBold(isBold);
   font.setColor(color);
   font.setFontHeight(fontHeight);
   font.setFontName(fontName);
   font.setItalic(isItalic);
   font.setStrikeout(isStrikeout);
   font.setTypeOffset(typeOffset);
   font.setUnderline(underline);
  }

  return font;
 }

 public static void main(String[] args) throws Exception {
  Workbook wb = WorkbookFactory.create(new FileInputStream("ExcelTest.xlsx"));

  DataFormatter formatter = new DataFormatter();

  Sheet sheet = wb.getSheetAt(0);

  Row row = null;
  Cell cell = null;
  Font font = null; 
  Map<String, Object> styleproperties = null;
  Map<FontProperty, Object> fontproperties = null;

  //turn cell A2 into numeric, font size 16pt and green fill color:
  //get cell A2
  row = CellUtil.getRow(1, sheet);
  cell = CellUtil.getCell(row, 0);

  //get old cell value and set it as numeric
  String cellvalue = formatter.formatCellValue(cell); 
  cell.setCellValue(Double.valueOf(cellvalue));

  //get the needed font
  fontproperties = new HashMap<FontProperty, Object>();
  fontproperties.put(FontProperty.FONTHEIGHT, (short)(16*20));
  font = getFont(wb, getFont(cell), fontproperties);

  //set new cell style properties
  styleproperties = new HashMap<String, Object>();
  styleproperties.put(CellUtil.DATA_FORMAT, BuiltinFormats.getBuiltinFormat("General"));
  styleproperties.put(CellUtil.FILL_FOREGROUND_COLOR, IndexedColors.GREEN.getIndex());
  styleproperties.put(CellUtil.FILL_PATTERN, FillPatternType.SOLID_FOREGROUND);
  styleproperties.put(CellUtil.FONT, font.getIndex());
  CellUtil.setCellStyleProperties(cell, styleproperties);

  //get data format from B1
  row = CellUtil.getRow(0, sheet);
  cell = CellUtil.getCell(row, 1);
  short dataFormatB1 = cell.getCellStyle().getDataFormat();

  //turn B2 into same data format as B1 and italic font:
  //get cell B2
  row = CellUtil.getRow(1, sheet);
  cell = CellUtil.getCell(row, 1);

  //get the needed font
  fontproperties = new HashMap<FontProperty, Object>();
  fontproperties.put(FontProperty.ITALIC, true);
  font = getFont(wb, getFont(cell), fontproperties);

  //set new cell style properties
  styleproperties = new HashMap<String, Object>();
  styleproperties.put(CellUtil.DATA_FORMAT, dataFormatB1);
  styleproperties.put(CellUtil.FONT, font.getIndex());
  CellUtil.setCellStyleProperties(cell, styleproperties);

  //set new cell D6 having special font settings
  row = CellUtil.getRow(5, sheet);
  cell = CellUtil.getCell(row, 3);
  fontproperties = new HashMap<FontProperty, Object>();
  fontproperties.put(FontProperty.BOLD, true);
  fontproperties.put(FontProperty.COLOR, IndexedColors.BLUE.getIndex());
  fontproperties.put(FontProperty.FONTHEIGHT, (short)(20*20));
  fontproperties.put(FontProperty.FONTNAME, "Courier New");
  fontproperties.put(FontProperty.STRIKEOUT, true);
  fontproperties.put(FontProperty.UNDERLINE, Font.U_DOUBLE);
  font = getFont(wb, getFont(cell), fontproperties);
  styleproperties = new HashMap<String, Object>();
  styleproperties.put(CellUtil.FONT, font.getIndex());
  CellUtil.setCellStyleProperties(cell, styleproperties);
  cell.setCellValue("new cell");

  //set new cell C4 having special font settings
  row = CellUtil.getRow(3, sheet);
  cell = CellUtil.getCell(row, 2);
  fontproperties = new HashMap<FontProperty, Object>();
  fontproperties.put(FontProperty.BOLD, true);
  fontproperties.put(FontProperty.COLOR, IndexedColors.DARK_RED.getIndex());
  fontproperties.put(FontProperty.FONTHEIGHT, (short)(42*20));
  fontproperties.put(FontProperty.FONTNAME, "Times New Roman");
  fontproperties.put(FontProperty.ITALIC, true);
  font = getFont(wb, getFont(cell), fontproperties);
  styleproperties = new HashMap<String, Object>();
  styleproperties.put(CellUtil.FONT, font.getIndex());
  CellUtil.setCellStyleProperties(cell, styleproperties);
  //set rich textt string into that cell
  RichTextString richString = new XSSFRichTextString("E = m c2");
                                                    //^0     ^7
  fontproperties = new HashMap<FontProperty, Object>();
  fontproperties.put(FontProperty.TYPEOFFSET, Font.SS_SUPER);
  font = getFont(wb, getFont(cell), fontproperties);
  richString.applyFont(7, 8, font);
  cell.setCellValue(richString);

  wb.write(new FileOutputStream("ExcelTestNew.xlsx"));
  wb.close();
 }  
}

结果:

【讨论】:

  • 我对这个答案有点困惑。 OP 询问如何使用日期格式格式化单元格。这个答案主要是关于格式化字体。如果有的话,最好能更清楚地说明发生这种情况的确切位置。
  • @chrismacp:Kuan 的真正目的在它的最后一条评论中给出。我已经适当地更新了问题。
  • 啊,是的!完全错过了。我只是想找出 B1 的日期格式是如何设置的,但似乎从来没有。
  • @chrismacp:单元格B1 已经存储在初始ExcelTest.xlsx 中并且已经是一个日期。所以它必须已经设置为日期格式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-18
  • 2022-11-13
相关资源
最近更新 更多