¿Cómo configuro el valor de la celda en Fecha y aplico el formato de fecha predeterminado de Excel?

101

He estado usando Apache POI durante algún tiempo para leer los archivos existentes de Excel 2003 mediante programación. Ahora tengo un nuevo requisito para crear archivos .xls completos en memoria (aún usando Apache POI) y luego escribirlos en un archivo al final. El único problema que se interpone en mi camino es el manejo de celdas con fechas.

Considere el siguiente código:

Date myDate = new Date();
HSSFCell myCell;
// code that assigns a cell from an HSSFSheet to 'myCell' would go here...
myCell.setCellValue(myDate);

Cuando escribo el libro de trabajo que contiene esta celda en un archivo y lo abro con Excel, la celda se muestra como un número. Sí, me doy cuenta de que Excel almacena sus 'fechas' como el número de días desde el 1 de enero de 1900 y eso es lo que representa el número en la celda.

PREGUNTA: ¿Qué llamadas API puedo usar en POI para decirle que quiero que se aplique un formato de fecha predeterminado a mi celda de fecha?

Idealmente, quiero que la celda de la hoja de cálculo se muestre con el mismo formato de fecha predeterminado que Excel le habría asignado si un usuario hubiera abierto manualmente la hoja de cálculo en Excel y hubiera escrito un valor de celda que Excel reconoció como una fecha.

Jim Tough
fuente

Respuestas:

172

http://poi.apache.org/spreadsheet/quick-guide.html#CreateDateCells

CellStyle cellStyle = wb.createCellStyle();
CreationHelper createHelper = wb.getCreationHelper();
cellStyle.setDataFormat(
    createHelper.createDataFormat().getFormat("m/d/yy h:mm"));
cell = row.createCell(1);
cell.setCellValue(new Date());
cell.setCellStyle(cellStyle);
ninja
fuente
21
Gracias ninja, esto funciona para mí. Un comentario para otros que necesiten hacer esto. Hay una clase de PDI nombrada BuiltinFormatsque enumera todos los formatos estándar (no solo los formatos de fecha) que conoce Excel. Me quedo con uno de esos para usar como mi parámetro para el getFormat()método que se muestra en el fragmento de arriba.
Jim Tough
La parte importante está en los comentarios del enlace: diseñamos la segunda celda como una fecha (y hora). Es importante crear un nuevo estilo de celda desde el libro de trabajo, de lo contrario, puede terminar modificando el estilo incorporado y afectando no solo a esta celda sino a otras celdas.
CGK
Gracias, @ninja. ¿Sabes por qué getCreationHelper()se necesita? Estoy trabajando con Mule en este momento para generar un archivo de salida de Excel y, de hecho, pude usar el createDataFormat()sin el asistente de creación y generé un archivo de Excel en mi prueba. ¿Hay alguna desventaja de no usarlo? ¡Gracias!
Rashiki
@Rashiki Esta respuesta fue publicada hace 6 años. Supongo que la API de Apache POI ha cambiado durante este tiempo. Mi respuesta a tu pregunta es 'No, no hay inconvenientes (si funciona como se esperaba)'
ninja
No veo ningún formato para mm/dd/yyyy. Cuando uso cualquier otro formato, Excel muestra un error File error, some number formats may have been lost, muestra el Datetipo en Excel. No tengo ni idea de cómo se puede solucionar esto.
Akash
24

Para configurar el tipo de Excel predeterminado Fecha (predeterminado en la configuración regional de nivel de sistema operativo / -> es decir, xlsx se verá diferente cuando lo abra una persona alemana o británica / y se marque con un asterisco si lo elige en el selector de formato de celda de Excel) debe:

    CellStyle cellStyle = xssfWorkbook.createCellStyle();
    cellStyle.setDataFormat((short)14);
    cell.setCellStyle(cellStyle);

Lo hice con xlsx y funcionó bien.

BlondCode
fuente
2
Absolutamente de acuerdo con el comentario de Fiffy. Solo tengo una pregunta. Cuál es el mejor enfoque. Confíe en el valor corto de dataFormat (14) o el valor de cadena ("m / d / aa"). ¿Cuál es realmente el valor constante que describe el formato de fecha estándar en Excel? DataFormat.getFormat () tiene tanto con cadena como con valor corto como parámetro.
Miklos Krivan
Miklos, no sé cómo funciona la solución de valor de cadena. Me alegraría si alguien pudiera comentar si eso también muestra el "formato de fecha predeterminado diferente basado en el idioma" en Excels con diferentes idiomas también.
BlondCode
13

Este ejemplo es para trabajar con tipos de archivo .xlsx. Este ejemplo proviene de una página .jsp utilizada para crear una hoja de cálculo .xslx.

import org.apache.poi.xssf.usermodel.*; //import needed

XSSFWorkbook  wb = new XSSFWorkbook ();  // Create workbook
XSSFSheet sheet = wb.createSheet();      // Create spreadsheet in workbook
XSSFRow row = sheet.createRow(rowIndex); // Create the row in the spreadsheet


//1. Create the date cell style
XSSFCreationHelper createHelper = wb.getCreationHelper();
XSSFCellStyle cellStyle         = wb.createCellStyle();
cellStyle.setDataFormat(
createHelper.createDataFormat().getFormat("MMMM dd, yyyy")); 

//2. Apply the Date cell style to a cell

//This example sets the first cell in the row using the date cell style
cell = row.createCell(0);
cell.setCellValue(new Date());
cell.setCellStyle(cellStyle);
Sr. Port St Joe
fuente
1

Estoy escribiendo mi respuesta aquí porque puede ser útil para otros lectores, que podrían tener un requisito ligeramente diferente al de quien preguntó aquí.

Preparo una plantilla .xlsx; todas las celdas que se llenarán con fechas, ya están formateadas como celdas de fecha (usando Excel).

Abro la plantilla .xlsx usando Apache POI y luego escribo la fecha en la celda, y funciona.

En el siguiente ejemplo, la celda A1 ya está formateada desde Excel con el formato [$-409]mmm yyyy, y el código Java se usa solo para completar la celda.

FileInputStream inputStream = new FileInputStream(new File("Path to .xlsx template"));
Workbook wb = new XSSFWorkbook(inputStream);
Date date1=new Date();
Sheet xlsMainTable = (Sheet) wb.getSheetAt(0);
Row myRow= CellUtil.getRow(0, xlsMainTable);
CellUtil.getCell(myRow, 0).setCellValue(date1);

Cuando se abre Excel, la fecha se formatea correctamente.

gordon613
fuente
0

Este ejemplo de código se puede utilizar para cambiar el formato de fecha. Aquí quiero cambiar de aaaa-MM-dd a dd-MM-aaaa. Aquí posestá la posición de la columna.

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

class Test{ 
public static void main( String[] args )
{
String input="D:\\somefolder\\somefile.xlsx";
String output="D:\\somefolder\\someoutfile.xlsx"
FileInputStream file = new FileInputStream(new File(input));
XSSFWorkbook workbook = new XSSFWorkbook(file);
XSSFSheet sheet = workbook.getSheetAt(0);
Iterator<Row> iterator = sheet.iterator();
Cell cell = null;
Row row=null;
row=iterator.next();
int pos=5; // 5th column is date.
while(iterator.hasNext())
{
    row=iterator.next();

    cell=row.getCell(pos-1);
    //CellStyle cellStyle = wb.createCellStyle();
    XSSFCellStyle cellStyle = (XSSFCellStyle)cell.getCellStyle();
    CreationHelper createHelper = wb.getCreationHelper();
    cellStyle.setDataFormat(
        createHelper.createDataFormat().getFormat("dd-MM-yyyy"));
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    Date d=null;
    try {
        d= sdf.parse(cell.getStringCellValue());
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        d=null;
        e.printStackTrace();
        continue;
    }
    cell.setCellValue(d);
    cell.setCellStyle(cellStyle);
   }

file.close();
FileOutputStream outFile =new FileOutputStream(new File(output));
workbook.write(outFile);
workbook.close();
outFile.close();
}}
Gaurav Khare
fuente
0

Para conocer la cadena de formato que usa Excel sin tener que adivinarla: cree un archivo de Excel, escriba una fecha en la celda A1 y formatéelo como desee. Luego ejecute las siguientes líneas:

FileInputStream fileIn = new FileInputStream("test.xlsx");
Workbook workbook = WorkbookFactory.create(fileIn);
CellStyle cellStyle = workbook.getSheetAt(0).getRow(0).getCell(0).getCellStyle();
String styleString = cellStyle.getDataFormatString();
System.out.println(styleString);

Luego copie y pegue la cadena resultante, elimine las barras invertidas (por ejemplo, se d/m/yy\ h\.mm;@convierte en d/m/yy h.mm;@) y utilícela en el código http://poi.apache.org/spreadsheet/quick-guide.html#CreateDateCells :

CellStyle cellStyle = wb.createCellStyle();
CreationHelper createHelper = wb.getCreationHelper();
cellStyle.setDataFormat(createHelper.createDataFormat().getFormat("d/m/yy h.mm;@"));
cell = row.createCell(1);
cell.setCellValue(new Date());
cell.setCellStyle(cellStyle);
Luke
fuente