How to format Excel Cell as Date in Apache POI as

2019-06-01 18:08发布

问题:

I am pretty new to Apache POI, I wonder how to do that Format Painter operation to format a cell into Date format, each time when I try to copy the date format of cell, in POI, it can only give me Numeric, I wonder how can I keep the date format?

    // 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);

And I need to change some other style, like border, background color, font italic, etcs. Could you give out one example: create one xlsx file, set 1A to number( say 10 ), 2A to text ("10") 1B to date(01/12/2018), 2B to 10000(just a number), then try to turn 2A into number with font 16 and green cell background, and turn 2B into date with same format as 1B but italic font.

回答1:

As said in comment already, the issue is not reproducible having your code snippet only. That shows why Minimal, Complete, and Verifiable examples are necessary.

I suspect the following: You are having the snippet in a loop and do changing the same style style_to multiple times having different style_from as source. This is possible since multiple cells cell_to may sharing the same style.

Manipulating cell styles for Excel spreadsheets is not as simple as one may think. The cell styles are stored on workbook level and are limited to 64,000 unique cell formats/cell styles in modern Excel versions. So one must be careful with new creating cell styles. At least one should not trying creating a new cell style for each single cell.

Apache poi provides CellUtil which has various utility functions that make working with a cells and rows easier. The various methods that deal with style's allow you to create your CellStyles as you need them. When you apply a style change to a cell, the code will attempt to see if a style already exists that meets your needs. If not, then it will create a new style. This is to prevent creating too many styles. What lacks until now is the same utility functions for dealing with fonts. Fonts also are on workbook level and so also should not being created without care.

The following example provides utility functions for creating fonts too.

It takes the ExcelTest.xlsx as you had described in your last comment and makes the changings you also had described there. It also makes some additional changings to show how the utility functions are working.

Source:

Code:

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

Result: