Java poi excel html

Did you look at this?: http://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/ss/examples/html/ToHtml.java

    /* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================== */
package org.apache.poi.ss.examples.html;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Formatter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.format.CellFormat;
import org.apache.poi.ss.format.CellFormatResult;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * This example shows how to display a spreadsheet in HTML using the classes for
 * spreadsheet display.
 */
public class ToHtml {
    private final Workbook wb;
    private final Appendable output;
    private boolean completeHTML;
    private Formatter out;
    private boolean gotBounds;
    private int firstColumn;
    private int endColumn;
    private HtmlHelper helper;

    private static final String DEFAULTS_CLASS = "excelDefaults";
    private static final String COL_HEAD_CLASS = "colHeader";
    private static final String ROW_HEAD_CLASS = "rowHeader";

    private static final Map<HorizontalAlignment, String> HALIGN = mapFor(
            HorizontalAlignment.LEFT, "left",
            HorizontalAlignment.CENTER, "center",
            HorizontalAlignment.RIGHT, "right",
            HorizontalAlignment.FILL, "left",
            HorizontalAlignment.JUSTIFY, "left",
            HorizontalAlignment.CENTER_SELECTION, "center");

    private static final Map<VerticalAlignment, String> VALIGN = mapFor(
            VerticalAlignment.BOTTOM, "bottom",
            VerticalAlignment.CENTER, "middle",
            VerticalAlignment.TOP, "top");

    private static final Map<BorderStyle, String> BORDER = mapFor(
            BorderStyle.DASH_DOT, "dashed 1pt",
            BorderStyle.DASH_DOT_DOT, "dashed 1pt",
            BorderStyle.DASHED, "dashed 1pt",
            BorderStyle.DOTTED, "dotted 1pt",
            BorderStyle.DOUBLE, "double 3pt",
            BorderStyle.HAIR, "solid 1px",
            BorderStyle.MEDIUM, "solid 2pt",
            BorderStyle.MEDIUM_DASH_DOT, "dashed 2pt",
            BorderStyle.MEDIUM_DASH_DOT_DOT, "dashed 2pt",
            BorderStyle.MEDIUM_DASHED, "dashed 2pt",
            BorderStyle.NONE, "none",
            BorderStyle.SLANTED_DASH_DOT, "dashed 2pt",
            BorderStyle.THICK, "solid 3pt",
            BorderStyle.THIN, "dashed 1pt");

    @SuppressWarnings({"unchecked"})
    private static <K, V> Map<K, V> mapFor(Object... mapping) {
        Map<K, V> map = new HashMap<K, V>();
        for (int i = 0; i < mapping.length; i += 2) {
            map.put((K) mapping[i], (V) mapping[i + 1]);
        }
        return map;
    }

    /**
     * Creates a new converter to HTML for the given workbook.
     *
     * @param wb     The workbook.
     * @param output Where the HTML output will be written.
     *
     * @return An object for converting the workbook to HTML.
     */
    public static ToHtml create(Workbook wb, Appendable output) {
        return new ToHtml(wb, output);
    }

    /**
     * Creates a new converter to HTML for the given workbook.  If the path ends
     * with "<tt>.xlsx</tt>" an {@link XSSFWorkbook} will be used; otherwise
     * this will use an {@link HSSFWorkbook}.
     *
     * @param path   The file that has the workbook.
     * @param output Where the HTML output will be written.
     *
     * @return An object for converting the workbook to HTML.
     */
    public static ToHtml create(String path, Appendable output)
            throws IOException {
        return create(new FileInputStream(path), output);
    }

    /**
     * Creates a new converter to HTML for the given workbook.  This attempts to
     * detect whether the input is XML (so it should create an {@link
     * XSSFWorkbook} or not (so it should create an {@link HSSFWorkbook}).
     *
     * @param in     The input stream that has the workbook.
     * @param output Where the HTML output will be written.
     *
     * @return An object for converting the workbook to HTML.
     */
    public static ToHtml create(InputStream in, Appendable output)
            throws IOException {
        try {
            Workbook wb = WorkbookFactory.create(in);
            return create(wb, output);
        } catch (InvalidFormatException e){
            throw new IllegalArgumentException("Cannot create workbook from stream", e);
        }
    }

    private ToHtml(Workbook wb, Appendable output) {
        if (wb == null) {
            throw new NullPointerException("wb");
        }
        if (output == null) {
            throw new NullPointerException("output");
        }
        this.wb = wb;
        this.output = output;
        setupColorMap();
    }

    private void setupColorMap() {
        if (wb instanceof HSSFWorkbook) {
            helper = new HSSFHtmlHelper((HSSFWorkbook) wb);
        } else if (wb instanceof XSSFWorkbook) {
            helper = new XSSFHtmlHelper();
        } else {
            throw new IllegalArgumentException(
                    "unknown workbook type: " + wb.getClass().getSimpleName());
        }
    }

    /**
     * Run this class as a program
     *
     * @param args The command line arguments.
     *
     * @throws Exception Exception we don't recover from.
     */
    public static void main(String[] args) throws Exception {
        if(args.length < 2){
            System.err.println("usage: ToHtml inputWorkbook outputHtmlFile");
            return;
        }

        ToHtml toHtml = create(args[0], new PrintWriter(new FileWriter(args[1])));
        toHtml.setCompleteHTML(true);
        toHtml.printPage();
    }

    public void setCompleteHTML(boolean completeHTML) {
        this.completeHTML = completeHTML;
    }

    public void printPage() throws IOException {
        try {
            ensureOut();
            if (completeHTML) {
                out.format(
                        "<?xml version="1.0" encoding="iso-8859-1" ?>%n");
                out.format("<html>%n");
                out.format("<head>%n");
                out.format("</head>%n");
                out.format("<body>%n");
            }

            print();

            if (completeHTML) {
                out.format("</body>%n");
                out.format("</html>%n");
            }
        } finally {
            IOUtils.closeQuietly(out);
            if (output instanceof Closeable) {
                IOUtils.closeQuietly((Closeable) output);
            }
        }
    }

    public void print() {
        printInlineStyle();
        printSheets();
    }

    private void printInlineStyle() {
        //out.format("<link href="excelStyle.css" rel="stylesheet" type="text/css">%n");
        out.format("<style type="text/css">%n");
        printStyles();
        out.format("</style>%n");
    }

    private void ensureOut() {
        if (out == null) {
            out = new Formatter(output);
        }
    }

    public void printStyles() {
        ensureOut();

        // First, copy the base css
        BufferedReader in = null;
        try {
            in = new BufferedReader(new InputStreamReader(
                    getClass().getResourceAsStream("excelStyle.css")));
            String line;
            while ((line = in.readLine()) != null) {
                out.format("%s%n", line);
            }
        } catch (IOException e) {
            throw new IllegalStateException("Reading standard css", e);
        } finally {
            IOUtils.closeQuietly(in);
        }

        // now add css for each used style
        Set<CellStyle> seen = new HashSet<CellStyle>();
        for (int i = 0; i < wb.getNumberOfSheets(); i++) {
            Sheet sheet = wb.getSheetAt(i);
            Iterator<Row> rows = sheet.rowIterator();
            while (rows.hasNext()) {
                Row row = rows.next();
                for (Cell cell : row) {
                    CellStyle style = cell.getCellStyle();
                    if (!seen.contains(style)) {
                        printStyle(style);
                        seen.add(style);
                    }
                }
            }
        }
    }

    private void printStyle(CellStyle style) {
        out.format(".%s .%s {%n", DEFAULTS_CLASS, styleName(style));
        styleContents(style);
        out.format("}%n");
    }

    private void styleContents(CellStyle style) {
        styleOut("text-align", style.getAlignmentEnum(), HALIGN);
        styleOut("vertical-align", style.getVerticalAlignmentEnum(), VALIGN);
        fontStyle(style);
        borderStyles(style);
        helper.colorStyles(style, out);
    }

    private void borderStyles(CellStyle style) {
        styleOut("border-left", style.getBorderLeftEnum(), BORDER);
        styleOut("border-right", style.getBorderRightEnum(), BORDER);
        styleOut("border-top", style.getBorderTopEnum(), BORDER);
        styleOut("border-bottom", style.getBorderBottomEnum(), BORDER);
    }

    private void fontStyle(CellStyle style) {
        Font font = wb.getFontAt(style.getFontIndex());

        if (font.getBold()) {
            out.format("  font-weight: bold;%n");
        }
        if (font.getItalic()) {
            out.format("  font-style: italic;%n");
        }

        int fontheight = font.getFontHeightInPoints();
        if (fontheight == 9) {
            //fix for stupid ol Windows
            fontheight = 10;
        }
        out.format("  font-size: %dpt;%n", fontheight);

        // Font color is handled with the other colors
    }

    private String styleName(CellStyle style) {
        if (style == null) {
            style = wb.getCellStyleAt((short) 0);
        }
        StringBuilder sb = new StringBuilder();
        Formatter fmt = new Formatter(sb);
        try {
            fmt.format("style_%02x", style.getIndex());
            return fmt.toString();
        } finally {
            fmt.close();
        }
    }

    private <K> void styleOut(String attr, K key, Map<K, String> mapping) {
        String value = mapping.get(key);
        if (value != null) {
            out.format("  %s: %s;%n", attr, value);
        }
    }

    private static CellType ultimateCellType(Cell c) {
        CellType type = c.getCellTypeEnum();
        if (type == CellType.FORMULA) {
            type = c.getCachedFormulaResultTypeEnum();
        }
        return type;
    }

    private void printSheets() {
        ensureOut();
        Sheet sheet = wb.getSheetAt(0);
        printSheet(sheet);
    }

    public void printSheet(Sheet sheet) {
        ensureOut();
        out.format("<table class=%s>%n", DEFAULTS_CLASS);
        printCols(sheet);
        printSheetContent(sheet);
        out.format("</table>%n");
    }

    private void printCols(Sheet sheet) {
        out.format("<col/>%n");
        ensureColumnBounds(sheet);
        for (int i = firstColumn; i < endColumn; i++) {
            out.format("<col/>%n");
        }
    }

    private void ensureColumnBounds(Sheet sheet) {
        if (gotBounds) {
            return;
        }

        Iterator<Row> iter = sheet.rowIterator();
        firstColumn = (iter.hasNext() ? Integer.MAX_VALUE : 0);
        endColumn = 0;
        while (iter.hasNext()) {
            Row row = iter.next();
            short firstCell = row.getFirstCellNum();
            if (firstCell >= 0) {
                firstColumn = Math.min(firstColumn, firstCell);
                endColumn = Math.max(endColumn, row.getLastCellNum());
            }
        }
        gotBounds = true;
    }

    private void printColumnHeads() {
        out.format("<thead>%n");
        out.format("  <tr class=%s>%n", COL_HEAD_CLASS);
        out.format("    <th class=%s>◊</th>%n", COL_HEAD_CLASS);
        //noinspection UnusedDeclaration
        StringBuilder colName = new StringBuilder();
        for (int i = firstColumn; i < endColumn; i++) {
            colName.setLength(0);
            int cnum = i;
            do {
                colName.insert(0, (char) ('A' + cnum % 26));
                cnum /= 26;
            } while (cnum > 0);
            out.format("    <th class=%s>%s</th>%n", COL_HEAD_CLASS, colName);
        }
        out.format("  </tr>%n");
        out.format("</thead>%n");
    }

    private void printSheetContent(Sheet sheet) {
        printColumnHeads();

        out.format("<tbody>%n");
        Iterator<Row> rows = sheet.rowIterator();
        while (rows.hasNext()) {
            Row row = rows.next();

            out.format("  <tr>%n");
            out.format("    <td class=%s>%d</td>%n", ROW_HEAD_CLASS,
                    row.getRowNum() + 1);
            for (int i = firstColumn; i < endColumn; i++) {
                String content = "&nbsp;";
                String attrs = "";
                CellStyle style = null;
                if (i >= row.getFirstCellNum() && i < row.getLastCellNum()) {
                    Cell cell = row.getCell(i);
                    if (cell != null) {
                        style = cell.getCellStyle();
                        attrs = tagStyle(cell, style);
                        //Set the value that is rendered for the cell
                        //also applies the format
                        CellFormat cf = CellFormat.getInstance(
                                style.getDataFormatString());
                        CellFormatResult result = cf.apply(cell);
                        content = result.text;
                        if (content.equals("")) {
                            content = "&nbsp;";
                        }
                    }
                }
                out.format("    <td class=%s %s>%s</td>%n", styleName(style),
                        attrs, content);
            }
            out.format("  </tr>%n");
        }
        out.format("</tbody>%n");
    }

    private String tagStyle(Cell cell, CellStyle style) {
        if (style.getAlignmentEnum() == HorizontalAlignment.GENERAL) {
            switch (ultimateCellType(cell)) {
            case STRING:
                return "style="text-align: left;"";
            case BOOLEAN:
            case ERROR:
                return "style="text-align: center;"";
            case NUMERIC:
            default:
                // "right" is the default
                break;
            }
        }
        return "";
    }
}

Рассказывает автор блога javarevisited.blogspot.ru


Из этой статьи вы сможете узнать о записи и чтении данных из Excel файлов в Java (будет рассмотрен как XLS, так и XLSX формат). Мы будем использовать библиотеку Apache POI и сосредоточимся на работе с типами String и Date, работа с последним происходит достаточно хитро. Напомню, что работу с числами мы уже рассмотрели в другой статье.

Библиотеку poi-XX.jar вы можете использовать для всех старых (xls, doc, ppt) файлов Microsoft Office, для новых (xlsx, docx, pptx) вам понадобится poi-ooxml-XX.jar. Очень важно понимать, что к чему относится, т.к. используемые классы тоже разные — для старых расширений это HSSFWorkbook, а для новых — XSSFWorkbook.

Подготовка: загрузка библиотек и зависимостей

Конечно, существует достаточно много открытых библиотек, которые позволяют работать с Excel файлами в Java, например, JXL, но мы будем использовать имеющую самый обширный API и самую популярную — Apache POI. Чтобы её использовать, вам нужно скачать jar файлы и добавить их через Eclipse вручную, или вы можете предоставить это Maven.

Во втором случае вам нужно просто добавить следующие две зависимости:

<dependencies>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>3.12</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>3.12</version>
    </dependency>
  </dependencies>

Самое удобное в Maven — что он загрузит не только указанные poi.jar и poi-ooxml.jar, но и все jar файлы, которые используются внутри, то есть xmlbeans-2.6.0.jar, stax-api-1.0.1.jar, poi-ooxml-schemas-3.12.jar и commons-codec-1.9.jar.

Если вы будете добавлять библиотеки вручную — не забудьте о вышеназванных файлах. Скачать всё можно отсюда. Помните — если вы загрузите только poi-XX.jar, то ваш код скомпилируется без ошибок, но потом упадёт с java.lang.NoClassDefFoundError: org/apache/xmlbeans/XmlObject, так как внутри будет вызываться xmlbeans.jar.

Запись

В этом примере мы запишем в xls файл следующие данные: в первую ячейку — строку с именем, а во вторую — дату рождения. Вот пошаговая инструкция:

  • Создаём объект HSSFWorkBook;
  • Создаём лист, используя на объекте, созданном в предыдущем шаге, createSheet();
  • Создаём на листе строку, используя createRow();
  • Создаём в строке ячейку — createCell();
  • Задаём значение ячейки через setCellValue();
  • Записываем workbook в File через FileOutputStream;
  • Закрываем workbook, вызывая close().

Для записи строк или чисел этого вполне достаточно, но чтобы записать дату, нам понадобится сделать ещё кое-что:

  • Создать DateFormat;
  • Создать CellStyle;
  • Записать DateFormat в CellStyle;
  • Записать CellStyle в ячейку;
  • Теперь в эту ячейку можно записать объект Date через всё тот же setCellValue;
  • Чтобы дата поместилась в ячейку, нам нужно добавить столбцу свойство автоматически менять размер: sheet.autoSizeColumn(1).

Всё вместе это будет выглядеть так:

@SuppressWarnings("deprecation")
    public static void writeIntoExcel(String file) throws FileNotFoundException, IOException{
        Workbook book = new HSSFWorkbook();
        Sheet sheet = book.createSheet("Birthdays");

        // Нумерация начинается с нуля
        Row row = sheet.createRow(0); 
        
        // Мы запишем имя и дату в два столбца
        // имя будет String, а дата рождения --- Date,
        // формата dd.mm.yyyy
        Cell name = row.createCell(0);
        name.setCellValue("John");
        
        Cell birthdate = row.createCell(1);
        
        DataFormat format = book.createDataFormat();
        CellStyle dateStyle = book.createCellStyle();
        dateStyle.setDataFormat(format.getFormat("dd.mm.yyyy"));
        birthdate.setCellStyle(dateStyle);
        
 
        // Нумерация лет начинается с 1900-го
        birthdate.setCellValue(new Date(110, 10, 10));
        
        // Меняем размер столбца
        sheet.autoSizeColumn(1);
        
        // Записываем всё в файл
        book.write(new FileOutputStream(file));
        book.close();
    }

Чтение

Теперь мы считаем из только что созданного файла то, что мы туда записали.

  • Для начала создадим HSSFWorkBook, передав в конструктор FileInputStream;
  • Получаем лист, передавая в getSheet() его номер или название;
  • Получаем строку, используя getRow();
  • Получаем ячейку, используя getCell();
  • Узнаём тип ячейки, используя на ней getCellType();
  • В зависимости от типа ячейки, читаем её значения, используя getStringCellValue(), getNumericCellValue() или getDateCellValue();
  • Закрываем workbook используя close().

Напомню, что дату Excel хранит как числа, т.е. тип ячейки всё равно будет CELL_TYPE_NUMERIC.

В виде кода это будет выглядеть следующим образом:

public static void readFromExcel(String file) throws IOException{
        HSSFWorkbook myExcelBook = new HSSFWorkbook(new FileInputStream(file));
        HSSFSheet myExcelSheet = myExcelBook.getSheet("Birthdays");
        HSSFRow row = myExcelSheet.getRow(0);
        
        if(row.getCell(0).getCellType() == HSSFCell.CELL_TYPE_STRING){
            String name = row.getCell(0).getStringCellValue();
            System.out.println("name : " + name);
        }
        
        if(row.getCell(1).getCellType() == HSSFCell.CELL_TYPE_NUMERIC){
            Date birthdate = row.getCell(1).getDateCellValue();
            System.out.println("birthdate :" + birthdate);
        }
        
        myExcelBook.close();
        
    }

В заключение

Как уже упомналось выше, чтение из xlsx файлов ничем принципиально не отличается — нужно только вместо HSSFWorkBook, HSSFSheet, HSSFRow (и прочих) из poi-XX.jar использовать XSSFWorkBook, XSSFSheet, XSSFRow из poi-ooxml-XX.jar. Это всё, что вам нужно знать для чтения и записи в файлы Excel. Разумеется, с помощью библиотеки Apache POI вы можете сделать гораздо больше, но эта статья должна помочь вам быстрее в ней освоиться.

Перевод статьи «How to Read Write Excel file in Java — POI Example»

Требования: Преобразование Excel в HTML, поддержка изображений и поддержка нескольких листов.

Требования: 1. Бесплатный и открытый исходный код, 2. Поддержка кроссплатформенности.

дизайн:

1. Принять Apache POI;

2. При наличии нескольких листов содержимое следующего листа выравнивается вниз по HTML.

3. Изображения хранятся отдельно в виде файлов или сохраняются в файлах HTML в виде двоичных строк;

Остальные проблемы (при последующем улучшении):

1. Точное позиционирование положения изображения: текущее положение изображения будет смещено в некоторых случаях в HTML.

Excel:

HTML конвертируется из Excel:

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.converter.ExcelToHtmlConverter;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFPicture;
import org.apache.poi.hssf.usermodel.HSSFPictureData;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFShape;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.w3c.dom.Document;

/**
 * POI преобразует Excel2003 в HTML
 */
public class Excel2Html_03 {

	/**
	  * POI конвертирует Excel в HTML (содержит картинки, картинки сохраняются в виде файлов)
	 * 
	  * @param excel excel полный путь
	  * @param html html полный путь
	 */
	public static void genHtml(String excel, String html) throws Exception {
		 // Создать объект Excel ExcelToHtmlConverter
		ExcelToHtmlConverter convert = new ExcelToHtmlConverter(DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());
		 // имена столбцов не отображаются
		convert.setOutputColumnHeaders(false);
		 // номер строки не отображается
		convert.setOutputRowNumbers(false);
		 // Создание объекта книги POI
		InputStream input = new FileInputStream(excel);
		HSSFWorkbook wb = new HSSFWorkbook(input);
		 // Удалить имя каждого листа в Excel
		for (int i = 0; i < wb.getNumberOfSheets(); i++) {
			if (wb.getSheetAt(i) != null) {
				String sheetName = StringUtils.leftPad(" ", i + 1, " ");
				wb.setSheetName(i, sheetName);
			}
		}
		convert.processWorkbook(wb);

		 // Создать HTML-контент (без изображений)
		Document htmlDocument = convert.getDocument();
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		DOMSource domSource = new DOMSource(htmlDocument);
		StreamResult streamResult = new StreamResult(outStream);
		TransformerFactory tfFactory = TransformerFactory.newInstance();
		Transformer tf = tfFactory.newTransformer();
		tf.setOutputProperty(OutputKeys.ENCODING, "utf-8");
		tf.setOutputProperty(OutputKeys.INDENT, "yes");
		tf.setOutputProperty(OutputKeys.METHOD, "html");
		tf.transform(domSource, streamResult);
		outStream.close();
		String content = new String(outStream.toByteArray());

		 // Обработка изображений
		String htmlImg = getImgHtml(wb, html);
		if (!"".equals(htmlImg)) {
			int bodyIndex = content.lastIndexOf("</body>");
			String tbodyA = content.substring(0, bodyIndex);
			String tbodyB = content.substring(bodyIndex, content.length() - 1);
			StringBuilder sb = new StringBuilder();
			sb.append(tbodyA);
			sb.append(htmlImg);
			sb.append(tbodyB);
			content = sb.toString();
		}
		 // Генерируем файл HTML
		File file = new File(html);
		String htmlFolder = file.getParent();
		String htmlName = file.getName();
		FileUtils.writeStringToFile(new File(htmlFolder, htmlName), content, "utf-8");
	}

	/**
	  * Изображения в Excel конвертируются в HTML, а изображения сохраняются в виде файлов
	 * 
	  * @param wb Excel книга
	  * @param html полный путь к html файлу
	  * @return html о картинках
	 * @throws IOException
	 */
	public static String getImgHtml(HSSFWorkbook wb, String html) throws IOException {
		 // Получить изображение первого листа Excel
		Map<String, HSSFPictureData> pics = getSheetPictrues(wb);
		if (pics == null || pics.size() == 0) {
			return "";
		}
		 // Папка с картинками = html folder + html name
		File file = new File(html);
		String htmlFolder = file.getParent();
		String htmlName = file.getName();
		File imgFolder = new File(htmlFolder + "/" + htmlName.substring(0, htmlName.lastIndexOf(".")));
		 // Определяем, существует ли папка с картинками, создаем ее, если она не существует
		if (!imgFolder.exists() && !imgFolder.isDirectory()) {
			imgFolder.mkdirs();
		}
		StringBuilder sb = new StringBuilder();
		for (Map.Entry<String, HSSFPictureData> entry : pics.entrySet()) {
			HSSFPictureData pic = entry.getValue();
			 // Сохранить рисунок, путь к изображению = путь HTML / имя HTML / лист index_row number_column number_uuid.
			String ext = pic.suggestFileExtension();
			String imgName = entry.getKey() + "." + ext;
			byte[] data = pic.getData();
			 // Создать картинку
			FileOutputStream out = new FileOutputStream(imgFolder + "/" + imgName);
			out.write(data);
			out.close();
			 // Координаты картинки в Excel
			String[] arr = StringUtils.split(entry.getKey(), "_");
			Integer top = getTop(wb, Integer.parseInt(arr[0]), Integer.parseInt(arr[1]));
			Integer left = getLeft(wb.getSheetAt(Integer.parseInt(arr[0])), Integer.parseInt(arr[2]));
			String htmlImg = "<table style="position: absolute; left: " + left + "; top: " + top + "pt;">n<tbody>n<tr>n<td>n";
			htmlImg += "<image src="" + htmlName.substring(0, htmlName.lastIndexOf(".")) + "/" + imgName + "" />";
			htmlImg += "n</td>n</tr>n</tbody>n</table>n";
			sb.append(htmlImg);
		}
		return sb.toString();
	}

	/**
	  * Изображения в Excel преобразуются в HTML, а изображения хранятся в HTML-файлах в виде двоичных строк
	 * 
	  * @param wb Excel книга
	  * @param html полный путь к html файлу
	  * @return html о картинках
	 * @throws IOException
	 */
	public static String getImgHtml_Base64(HSSFWorkbook wb, String html) throws IOException {
		 // Получить изображение первого листа Excel
		Map<String, HSSFPictureData> pics = getSheetPictrues(wb);
		if (pics == null || pics.size() == 0) {
			return "";
		}
		StringBuilder sb = new StringBuilder();
		for (Map.Entry<String, HSSFPictureData> entry : pics.entrySet()) {
			HSSFPictureData pic = entry.getValue();
			byte[] data = pic.getData();
			String baseStr = Base64.getEncoder().encodeToString(data);
			 // Координаты картинки в Excel
			String[] arr = StringUtils.split(entry.getKey(), "_");
			Integer top = getTop(wb, Integer.parseInt(arr[0]), Integer.parseInt(arr[1]));
			Integer left = getLeft(wb.getSheetAt(Integer.parseInt(arr[0])), Integer.parseInt(arr[2]));
			String htmlImg = "<table style="position: absolute; left: " + left + "; top: " + top + "pt;">n<tbody>n<tr>n<td>n";
			htmlImg += "<image src="data:image/png;base64," + baseStr + "" />";
			htmlImg += "n</td>n</tr>n</tbody>n</table>n";
			sb.append(htmlImg);
		}
		return sb.toString();
	}

	/**
	  * Получение изображения Excel
	 * 
	  * @param wb Excel книга
	  * Изображение @return Excel, формат ключа: лист index_row number_column number_uuid
	 */
	public static Map<String, HSSFPictureData> getSheetPictrues(HSSFWorkbook wb) {
		Map<String, HSSFPictureData> map = new HashMap<String, HSSFPictureData>();
		 // Метод getAllPictures может получить только разные изображения, если в Excel одинаковое изображение, можно получить только одно изображение
		List<HSSFPictureData> pics = wb.getAllPictures();
		if (pics.size() == 0) {
			return map;
		}
		for (Integer sheetIndex = 0; sheetIndex < wb.getNumberOfSheets(); sheetIndex++) {
			HSSFSheet sheet = wb.getSheetAt(sheetIndex);
			for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren()) {
				HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();
				if (shape instanceof HSSFPicture) {
					HSSFPicture pic = (HSSFPicture) shape;
					int picIndex = pic.getPictureIndex() - 1;
					HSSFPictureData picData = pics.get(picIndex);
					 // Формат ключа: лист index_row number_column number_uuid
					String key = sheetIndex + "_" + anchor.getRow1() + "_" + anchor.getCol1() + "_" + UUID.randomUUID();
					map.put(key, picData);
				}
			}
		}
		return map;
	}

	/**
	  * Верхнее поле ячейки в Excel (верхнее поле HTML), поддержка нескольких листов, приращение
	 * 
	  * @param wb Excel книга
	  * Индекс @param sheetIndex Sheet
	  * @param rowIndex номер строки ячейки, игнорируя внутреннее поле ячейки
	  * @ возврат приближения верхнего поля
	 */
	public static Integer getTop(HSSFWorkbook wb, Integer sheetIndex, Integer rowIndex) {
		Integer top = 0;
		HSSFSheet sheet = null;
		for (Integer i = 0; i < sheetIndex; i++) {
			sheet = wb.getSheetAt(i);
			 // Получить общее количество строк
			Integer rowNum = sheet.getLastRowNum();
			Integer height = getTop(sheet, rowNum + 1);
			top += height;
		}
		sheet = wb.getSheetAt(sheetIndex);
		top += getTop(sheet, rowIndex);
		return top;
	}

	/**
	  * Верхнее поле ячейки в листе (один лист)
	 * 
	  * @param sheet Лист Excel
	  * @param rowIndex номер строки ячейки, игнорируя внутреннее поле ячейки
	  * @ возврат приближения верхнего поля
	 */
	public static Integer getTop(HSSFSheet sheet, Integer rowIndex) {
		Integer top = 0;
		for (int i = 0; i < rowIndex; i++) {
			HSSFRow row = sheet.getRow(i);
			 // Исключить пустые строки (также исключаются во время преобразования HTML)
			if (row == null) {
				continue;
			}
			short height = row.getHeight();
			top += height;
		}
		return top / 20 + 1;
	}

	/**
	  * Левый край ячейки в листе
	 * 
	  * @param sheet Лист Excel
	  * @param colIndex номер столбца, где находится ячейка, игнорируя внутреннее поле
	  * @ возврат приблизительного значения левого поля
	 */
	public static Integer getLeft(HSSFSheet sheet, Integer colIndex) {
		Integer left = 0;
		for (int i = 0; i < colIndex; i++) {
			int width = sheet.getColumnWidth(i);
			left += width;
		}
		return left / 36 + 1;
	}

}

Афоризм

Деньги не люди, лишними не бывают.

Поддержка проекта

Если Вам сайт понравился и помог, то будем признательны за Ваш «посильный» вклад в его поддержку и развитие

 • Yandex.Деньги
  410013796724260

 • Webmoney
  R335386147728
  Z369087728698

Apache POI, взаимодействие с Excel

Apache POI представляет собой API, который позволяет использовать файлы MS Office в Java приложениях.
Данная библиотека разрабатывается и распространяется Apache Software Foundation и носит открытый характер.
Apache POI включает классы и методы для чтения и записи информации в документы MS Office.

Описание компонентов

HSSF Horrible Spreadsheet Format Компонент чтения и записи файлов MS-Excel, формат XLS
XSSF XML Spreadsheet Format Компонент чтения и записи файлов MS-Excel, формат XLSX
HPSF Horrible Property Set Format Компонент получения наборов свойств файлов MS-Office
HWPF Horrible Word Processor Format Компонент чтения и записи файлов MS-Word, формат DOC
XWPF XML Word Processor Format Компонент чтения и записи файлов MS-Word, формат DOCX
HSLF Horrible Slide Layout Format Компонент чтения и записи файлов PowerPoint, формат PPT
XSLF XML Slide Layout Format Компонент чтения и записи файлов PowerPoint, формат PPTX
HDGF Horrible DiaGram Format Компонент работы с файлами MS-Visio, формат VSD
XDGF XML DiaGram Format Компонент работы с файлами MS-Visio, формат VSDX

Список компонентов

Наименование (артeфакт) Необходимые компоненты
poi commons-logging, commons-codec, commons-collections, log4j
poi-scratchpad poi
poi-ooxml poi, poi-ooxml-schemas
poi-ooxml-schemas xmlbeans
poi-examples poi, poi-scratchpad, poi-ooxml
ooxml-schemas xmlbeans
ooxml-security xmlbeans

Подключение Apache POI к проекту

Для подключения Apache POI к проекту необходимо скачать соответствующие библиотеки с официального сайта
https://poi.apache.org/download.html.

Если в проекте используется фреймворк maven, то необходимо установить одну из
следующих зависимостей (версия может быть более новой) :

<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.16</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.16</version>
</dependency>

На странице описания примера чтения файлов Excel приведен проект, включающий
необходимый набор файлов библиотеки Apache POI (poi-3.16.jar, poi-ooxml-3.16.jar, poi-ooxml-schemas-3.16.jar) и
сопутствующих библиотек.

На странице рассматриваются следующие классы, используемые для работы с файлами Excel из приложений Java.

  • рабочая книга — HSSFWorkbook, XSSFWorkbook
  • лист книги — HSSFSheet, XSSFSheet
  • строка — HSSFRow, XSSFRow
  • ячейка — HSSFCell, XSSFCell
  • стиль — стили ячеек HSSFCellStyle, XSSFCellStyle
  • шрифт — шрифт ячеек HSSFFont, XSSFFont

Поскольку описание всех классов и методов не разместить на одной
странице, то ниже по тексту приводятся ссылки для перехода к исходной документации.

Классы и методы Apache POI для работы с файлами Excel

Рабочая книга HSSFWorkbook, XSSFWorkbook

  • HSSFWorkbook
    • org.apache.poi.hssf.usermodel
    • класс чтения и записи файлов Microsoft Excel в формате .xls, совместим
      с версиями MS-Office 97-2003;
  • XSSFWorkbook
    • org.apache.poi.xssf.usermodel
    • класс чтения и записи файлов Microsoft Excel в формате .xlsx, совместим
      с MS-Office 2007 или более поздней версии.

Конструкторы класса HSSFWorkbook

HSSFWorkbook ();
HSSFWorkbook (InternalWorkbook book);
HSSFWorkbook (POIFSFileSystem  fs);
HSSFWorkbook (NPOIFSFileSystem fs);
HSSFWorkbook (POIFSFileSystem  fs, 
              boolean preserveNodes);
HSSFWorkbook (DirectoryNode directory, 
              POIFSFileSystem fs, 
              boolean preserveNodes);
HSSFWorkbook (DirectoryNode directory,
              boolean preserveNodes);
HSSFWorkbook (InputStream s);
HSSFWorkbook (InputStream s, 
              boolean preserveNodes);

preservenodes является необязательным параметром, который определяет необходимость сохранения
узлов типа макросы.

Конструкторы класса XSSFWorkbook

XSSFWorkbook ();
// workbookType  создать .xlsx или .xlsm
XSSFWorkbook (XSSFWorkbookType workbookType);
XSSFWorkbook (OPCPackage   pkg );
XSSFWorkbook (InputStream  is  );
XSSFWorkbook (File         file);
XSSFWorkbook (String       path);

Основные методы HSSFWorkbook, XSSFWorkbook

Метод Описание
createSheet () Создание страницы книги HSSFSheet, XSSFSheet
createSheet (String name) Создание страницы с определенным наименованием
CreateFont () Создание шрифта
createCellStyle () Создание стиля

С полным перечнем всех методов класса XSSFWorkbook можно познакомиться на странице
http://poi.apache.org/apidocs/org/apache/poi/xssf/usermodel/XSSFWorkbook.html.

Классы листов книги, HSSFSheet, XSSFSheet

  • org.apache.poi.hssf.usermodel.HSSFSheet
  • org.apache.poi.xssf.usermodel.XSSFSheet

Классы HSSFSheet, XSSFSheet включают свойства и методы создания строк, определения размера колонок,
слияния ячеек в одну область и т.д.

Основные методы классов работы с листами

Метод Описание
addMergedRegion (CellRangeAddress) Определение области слияния ячеек страницы
autoSizeColumn (int column) Автоматическая настройка ширины колонки column (отсчет от 0)
setColumnWidth (int column, int width) Настройка ширины колонки column (отсчет от 0)
createRow (int row) Создание строки row (отсчет от 0)
getRow (int row) Получение ссылки на строку row (отсчет от 0)

С полным перечнем всех методов класса XSSFSheet можно познакомиться на странице
https://poi.apache.org/apidocs/org/apache/poi/xssf/usermodel/XSSFSheet.html

Классы строк HSSFRow, XSSFRow

  • org.apache.poi.hssf.usermodel.HSSFRow
  • org.apache.poi.xssf.usermodel.XSSFRow

Классы HSSFRow, XSSFRow включают свойства и методы работы со строками, создания ячеек в строке и т.д.

Основные методы классов HSSFRow, XSSFRow

Метод Описание
setHeight (short) Определение высоты строки
getHeight() Получение значения высоты в twips’ах (1/20)
getHeightInPoints() Получение значение высоты
createCell (int) Создание ячейки в строке (отсчет от 0)
getCell(int) Получение ссылки на ячейку
getFirstCellNum() Получение номера первой ячейки в строке
setRowStyle(CellStyle) Определение стиля всей строки

С полным перечнем всех методов класса XSSFRow можно познакомиться на странице
http://poi.apache.org/apidocs/org/apache/poi/xssf/usermodel/XSSFRow.html

Классы ячеек HSSFCell, XSSFCell

Ячейки электронной таблицы используются для размещения информации. В ячейке может быть представлено
числовое значение, текст или формула. Также ячейка может содержать комментарий.

Классы HSSFCell, XSSFCell включают свойства и методы работы с ячейками таблицы.

  • org.apache.poi.hssf.usermodel.HSSFCell
  • org.apache.poi.xssf.usermodel.XSSFCell

Основные методы классов HSSFCell, XSSFCell

Метод Описание
getBooleanCellValue() Чтение логического значения ячейки
getDateCellValue() Чтение значения ячейки типа java.util.Date
getNumericCellValue() Чтение числового значения ячейки типа double
getStringCellValue() Чтение текстового значения ячейки (java.lang.String)
setCellValue(boolean) Определение логического значения ячейки
setCellValue(java.util.Calendar) Определение значения ячейки типа даты
setCellValue(java.util.Date) Определение значения ячейки типа даты
getCellTypeEnum() Чтение типа значения ячейки CellType
setCellComment(Comment) Запись комментария в ячейку
getCellComment() Чтение комментария ячейки
removeCellComment() Удаление комментария ячейки
setHyperlink(Hyperlink) Запись гиперссылки в ячейку
getHyperlink() Чтение гиперссылки XSSFHyperlink в ячейке
removeHyperlink() Удаления гиперссылки ячейки
getCellFormula() Чтение формулы, например SUM(C4:E4)
setCellFormula(String) Определение формулы, например =SUM(C4:E4)
getCellStyle() Чтение стиля ячейки (XSSFCellStyle)
setCellStyle(CellStyle) Определение стиля ячейки
getColumnIndex() Определение индекса ячейки
setAsActiveCell() Определение активности ячейки

С полным перечнем всех методов класса XSSFCell можно познакомиться на странице
http://poi.apache.org/apidocs/org/apache/poi/xssf/usermodel/XSSFCell.html

Классы стилей ячеек HSSFCellStyle, XSSFCellStyle

С полным перечнем всех свойств и методов класса XSSFCellStyle можно познакомиться на странице
http://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/CellStyle.html

Ниже в качестве примера представлен метод, формирующий стиль ячейки, в которой :

  • текст центрируется по вертикали и горизонтали;
  • обрамление ячейки представляет тонкую черную линию по периметру;
  • текст переносится на следующую строку (не ячейку), если не вмещается в размер ячейки.
private XSSFCellStyle createCellStyle(XSSFWorkbook book)
{
    BorderStyle thin  = BorderStyle.THIN;
    short       black = IndexedColors.BLACK.getIndex();

    XSSFCellStyle style = book.createCellStyle();

    style.setWrapText(true);
    style.setAlignment        (HorizontalAlignment.CENTER);
    style.setVerticalAlignment(VerticalAlignment  .CENTER);

    style.setBorderTop        (thin);
    style.setBorderBottom     (thin);
    style.setBorderRight      (thin);
    style.setBorderLeft       (thin);

    style.setTopBorderColor   (black);
    style.setRightBorderColor (black);
    style.setBottomBorderColor(black);
    style.setLeftBorderColor  (black);

    return style;
}

Метод setWrapText позволяет определить флаг переноса текста в ячейке согласно ее размеру (ширине). Чтобы перенести
текст принудительно, можно в текстовой строке установить символы CRCL, например «Разделительrnтекста».

Классы шрифтов HSSFFont, XSSFFont

С полным перечнем всех свойств и методов класса XSSFFont можно познакомиться на странице
http://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Font.html

Ниже в качестве примера представлен метод, формирующий шрифт типа «Times New Roman» :

private XSSFFont createCellFont(XSSFWorkbook book)
{
    XSSFFont font = workBook.createFont();
    font.setFontHeightInPoints((short) 12);
    font.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
    font.setFontName("Times New Roman");
           
    return(font);
}
. . .
HSSFCellStyle style = book.createCellStyle();
style.setFont(createCellFont(book));

Примеры создания файлов Excel и определение стилей ячеек рассмотрены
здесь.

Learn to read excel, write excel, evaluate formula cells and apply custom formatting to the generated excel files using Apache POI library with examples.

If we are building software for the HR or Finance domain, there is usually a requirement for generating excel reports across management levels. Apart from reports, we can also expect some input data for the applications coming in the form of excel sheets and the application is expected to support this requirement.

Apache POI is a well-trusted library among many other open-source libraries to handle such usecases involving excel files. Please note that, in addition, we can read and write MS Word and MS PowerPoint files also using the Apache POI library.

This Apache POI tutorial will discuss some everyday excel operations in real-life applications.

  1. 1. Maven Dependency
  2. 2. Important Classes in POI Library
  3. 3. Writing an Excel File
  4. 4. Reading an Excel File
  5. 5. Add and Evaluate Formula Cells
  6. 6. Formatting the Cells
  7. 7. Conclusion

1. Maven Dependency

If we are working on a maven project, we can include the Apache POI dependencies in pom.xml file using this:

<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi</artifactId>
  <version>5.2.2</version>
</dependency>

<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi-ooxml</artifactId>
  <version>5.2.2</version>
</dependency>

2. Important Classes in POI Library

  1. HSSF, XSSF and XSSF classes

    Apache POI main classes usually start with either HSSF, XSSF or SXSSF.

    • HSSF – is the POI Project’s pure Java implementation of the Excel 97(-2007) file format. e.g., HSSFWorkbook, HSSFSheet.
    • XSSF – is the POI Project’s pure Java implementation of the Excel 2007 OOXML (.xlsx) file format. e.g., XSSFWorkbook, XSSFSheet.
    • SXSSF (since 3.8-beta3) – is an API-compatible streaming extension of XSSF to be used when huge spreadsheets have to be produced and heap space is limited. e.g., SXSSFWorkbook, SXSSFSheet. SXSSF achieves its low memory footprint by limiting access to the rows within a sliding window, while XSSF gives access to all rows in the document.
  2. Row and Cell

    Apart from the above classes, Row and Cell interact with a particular row and a particular cell in an excel sheet.

  3. Styling Related Classes

    A wide range of classes like CellStyle, BuiltinFormats, ComparisonOperator, ConditionalFormattingRule, FontFormatting, IndexedColors, PatternFormatting, SheetConditionalFormatting etc. are used when you have to add formatting to a sheet, primarily based on some rules.

  4. FormulaEvaluator

    Another helpful class FormulaEvaluator is used to evaluate the formula cells in an excel sheet.

3. Writing an Excel File

I am taking this example first so we can reuse the excel sheet created by this code in further examples.

Writing excel using POI is very simple and involves the following steps:

  1. Create a workbook
  2. Create a sheet in workbook
  3. Create a row in sheet
  4. Add cells to sheet
  5. Repeat steps 3 and 4 to write more data

It seems very simple, right? Let’s have a look at the code doing these steps.

Java program to write an excel file using Apache POI library.

package com.howtodoinjava.demo.poi;
//import statements
public class WriteExcelDemo 
{
    public static void main(String[] args) 
    {
        //Blank workbook
        XSSFWorkbook workbook = new XSSFWorkbook(); 
         
        //Create a blank sheet
        XSSFSheet sheet = workbook.createSheet("Employee Data");
          
        //This data needs to be written (Object[])
        Map<String, Object[]> data = new TreeMap<String, Object[]>();
        data.put("1", new Object[] {"ID", "NAME", "LASTNAME"});
        data.put("2", new Object[] {1, "Amit", "Shukla"});
        data.put("3", new Object[] {2, "Lokesh", "Gupta"});
        data.put("4", new Object[] {3, "John", "Adwards"});
        data.put("5", new Object[] {4, "Brian", "Schultz"});
          
        //Iterate over data and write to sheet
        Set<String> keyset = data.keySet();
        int rownum = 0;
        for (String key : keyset)
        {
            Row row = sheet.createRow(rownum++);
            Object [] objArr = data.get(key);
            int cellnum = 0;
            for (Object obj : objArr)
            {
               Cell cell = row.createCell(cellnum++);
               if(obj instanceof String)
                    cell.setCellValue((String)obj);
                else if(obj instanceof Integer)
                    cell.setCellValue((Integer)obj);
            }
        }
        try
        {
            //Write the workbook in file system
            FileOutputStream out = new FileOutputStream(new File("howtodoinjava_demo.xlsx"));
            workbook.write(out);
            out.close();
            System.out.println("howtodoinjava_demo.xlsx written successfully on disk.");
        } 
        catch (Exception e) 
        {
            e.printStackTrace();
        }
    }
}
poi-demo-write-file

See Also: Appending Rows to Excel

4. Reading an Excel File

Reading an excel file using POI is also very simple if we divide this into steps.

  1. Create workbook instance from an excel sheet
  2. Get to the desired sheet
  3. Increment row number
  4. iterate over all cells in a row
  5. repeat steps 3 and 4 until all data is read

Let’s see all the above steps in code. I am writing the code to read the excel file created in the above example. It will read all the column names and the values in it – cell by cell.

Java program to read an excel file using Apache POI library.

package com.howtodoinjava.demo.poi;
//import statements
public class ReadExcelDemo 
{
    public static void main(String[] args) 
    {
        try
        {
            FileInputStream file = new FileInputStream(new File("howtodoinjava_demo.xlsx"));
 
            //Create Workbook instance holding reference to .xlsx file
            XSSFWorkbook workbook = new XSSFWorkbook(file);
 
            //Get first/desired sheet from the workbook
            XSSFSheet sheet = workbook.getSheetAt(0);
 
            //Iterate through each rows one by one
            Iterator<Row> rowIterator = sheet.iterator();
            while (rowIterator.hasNext()) 
            {
                Row row = rowIterator.next();
                //For each row, iterate through all the columns
                Iterator<Cell> cellIterator = row.cellIterator();
                 
                while (cellIterator.hasNext()) 
                {
                    Cell cell = cellIterator.next();
                    //Check the cell type and format accordingly
                    switch (cell.getCellType()) 
                    {
                        case Cell.CELL_TYPE_NUMERIC:
                            System.out.print(cell.getNumericCellValue() + "t");
                            break;
                        case Cell.CELL_TYPE_STRING:
                            System.out.print(cell.getStringCellValue() + "t");
                            break;
                    }
                }
                System.out.println("");
            }
            file.close();
        } 
        catch (Exception e) 
        {
            e.printStackTrace();
        }
    }
}

Program Output:

ID      NAME        LASTNAME
1.0     Amit        Shukla  
2.0     Lokesh      Gupta   
3.0     John        Adwards 
4.0     Brian       Schultz 

See Also: Apache POI – Read an Excel File using SAX Parser

5. Add and Evaluate Formula Cells

When working on complex excel sheets, we encounter many cells with formulas to calculate their values. These are formula cells. Apache POI also has excellent support for adding formula cells and evaluating already present formula cells.

Let’s see one example of how to add formula cells in excel?

The sheet has four cells in a row and the fourth one in the multiplication of all the previous 3 rows. So the formula will be: A2*B2*C2 (in the second row)

Java program to add formula in an excel file using Apache POI library.

public static void main(String[] args) 
{
    XSSFWorkbook workbook = new XSSFWorkbook();
    XSSFSheet sheet = workbook.createSheet("Calculate Simple Interest");
  
    Row header = sheet.createRow(0);
    header.createCell(0).setCellValue("Pricipal");
    header.createCell(1).setCellValue("RoI");
    header.createCell(2).setCellValue("T");
    header.createCell(3).setCellValue("Interest (P r t)");
      
    Row dataRow = sheet.createRow(1);
    dataRow.createCell(0).setCellValue(14500d);
    dataRow.createCell(1).setCellValue(9.25);
    dataRow.createCell(2).setCellValue(3d);
    dataRow.createCell(3).setCellFormula("A2*B2*C2");
      
    try {
        FileOutputStream out =  new FileOutputStream(new File("formulaDemo.xlsx"));
        workbook.write(out);
        out.close();
        System.out.println("Excel with foumula cells written successfully");
          
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Similarly, we want to read a file with formula cells and use the following logic to evaluate formula cells.

Java program to evaluate formula in an excel file using Apache POI library.

public static void readSheetWithFormula()
{
    try
    {
        FileInputStream file = new FileInputStream(new File("formulaDemo.xlsx"));
 
        //Create Workbook instance holding reference to .xlsx file
        XSSFWorkbook workbook = new XSSFWorkbook(file);
 
        FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
         
        //Get first/desired sheet from the workbook
        XSSFSheet sheet = workbook.getSheetAt(0);
 
        //Iterate through each rows one by one
        Iterator<Row> rowIterator = sheet.iterator();
        while (rowIterator.hasNext()) 
        {
            Row row = rowIterator.next();
            //For each row, iterate through all the columns
            Iterator<Cell> cellIterator = row.cellIterator();
             
            while (cellIterator.hasNext()) 
            {
                Cell cell = cellIterator.next();
                //Check the cell type after eveluating formulae
                //If it is formula cell, it will be evaluated otherwise no change will happen
                switch (evaluator.evaluateInCell(cell).getCellType()) 
                {
                    case Cell.CELL_TYPE_NUMERIC:
                        System.out.print(cell.getNumericCellValue() + "tt");
                        break;
                    case Cell.CELL_TYPE_STRING:
                        System.out.print(cell.getStringCellValue() + "tt");
                        break;
                    case Cell.CELL_TYPE_FORMULA:
                        //Not again
                        break;
                }
            }
            System.out.println("");
        }
        file.close();
    } 
    catch (Exception e) 
    {
        e.printStackTrace();
    }
}

Program Output:

Pricipal        RoI         T       Interest (P r t)        
14500.0         9.25        3.0     402375.0  
poi-demo-write-formula

6. Formatting the Cells

So far we have seen examples of reading/writing and excel files using Apache POI. But, when creating a report in an excel file, it is essential to add formatting on cells that fit into any pre-determined criteria.

This formatting can be a different coloring based on a specific value range, expiry date limit etc.

In the below examples, we are taking a couple of such cell formatting examples for various purposes.

6.1. Cell value in a specific range

This code will color any cell in a range whose value is between a configured range. [e.g., between 50 and 70]

static void basedOnValue(Sheet sheet) 
{
    //Creating some random values
    sheet.createRow(0).createCell(0).setCellValue(84);
    sheet.createRow(1).createCell(0).setCellValue(74);
    sheet.createRow(2).createCell(0).setCellValue(50);
    sheet.createRow(3).createCell(0).setCellValue(51);
    sheet.createRow(4).createCell(0).setCellValue(49);
    sheet.createRow(5).createCell(0).setCellValue(41);
 
    SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
 
    //Condition 1: Cell Value Is   greater than  70   (Blue Fill)
    ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule(ComparisonOperator.GT, "70");
    PatternFormatting fill1 = rule1.createPatternFormatting();
    fill1.setFillBackgroundColor(IndexedColors.BLUE.index);
    fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
 
    //Condition 2: Cell Value Is  less than      50   (Green Fill)
    ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule(ComparisonOperator.LT, "50");
    PatternFormatting fill2 = rule2.createPatternFormatting();
    fill2.setFillBackgroundColor(IndexedColors.GREEN.index);
    fill2.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
 
    CellRangeAddress[] regions = {
            CellRangeAddress.valueOf("A1:A6")
    };
 
    sheetCF.addConditionalFormatting(regions, rule1, rule2);
}
poi-demo-formatting-1

6.2. Highlight Duplicate Values

Highlight all cells which have duplicate values in observed cells.

static void formatDuplicates(Sheet sheet) {
    sheet.createRow(0).createCell(0).setCellValue("Code");
    sheet.createRow(1).createCell(0).setCellValue(4);
    sheet.createRow(2).createCell(0).setCellValue(3);
    sheet.createRow(3).createCell(0).setCellValue(6);
    sheet.createRow(4).createCell(0).setCellValue(3);
    sheet.createRow(5).createCell(0).setCellValue(5);
    sheet.createRow(6).createCell(0).setCellValue(8);
    sheet.createRow(7).createCell(0).setCellValue(0);
    sheet.createRow(8).createCell(0).setCellValue(2);
    sheet.createRow(9).createCell(0).setCellValue(8);
    sheet.createRow(10).createCell(0).setCellValue(6);
 
    SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
 
    // Condition 1: Formula Is   =A2=A1   (White Font)
    ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("COUNTIF($A$2:$A$11,A2)>1");
    FontFormatting font = rule1.createFontFormatting();
    font.setFontStyle(false, true);
    font.setFontColorIndex(IndexedColors.BLUE.index);
 
    CellRangeAddress[] regions = {
            CellRangeAddress.valueOf("A2:A11")
    };
 
    sheetCF.addConditionalFormatting(regions, rule1);
 
    sheet.getRow(2).createCell(1).setCellValue("<== Duplicates numbers in the column are highlighted.  " +
            "Condition: Formula Is =COUNTIF($A$2:$A$11,A2)>1   (Blue Font)");
}
poi-demo-formatting-2

6.3. Alternate Color Rows in Different Colors

A simple code to color each alternate row in a different color.

static void shadeAlt(Sheet sheet) {
    SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
 
    // Condition 1: Formula Is   =A2=A1   (White Font)
    ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("MOD(ROW(),2)");
    PatternFormatting fill1 = rule1.createPatternFormatting();
    fill1.setFillBackgroundColor(IndexedColors.LIGHT_GREEN.index);
    fill1.setFillPattern(PatternFormatting.SOLID_FOREGROUND);
 
    CellRangeAddress[] regions = {
            CellRangeAddress.valueOf("A1:Z100")
    };
 
    sheetCF.addConditionalFormatting(regions, rule1);
 
    sheet.createRow(0).createCell(1).setCellValue("Shade Alternating Rows");
    sheet.createRow(1).createCell(1).setCellValue("Condition: Formula Is  =MOD(ROW(),2)   (Light Green Fill)");
}
poi-demo-formatting-3

6.4. Color amounts that are going to expire in the next 30 days

A handy code for financial projects which keeps track of deadlines.

static void expiryInNext30Days(Sheet sheet) 
{
    CellStyle style = sheet.getWorkbook().createCellStyle();
    style.setDataFormat((short)BuiltinFormats.getBuiltinFormat("d-mmm"));
 
    sheet.createRow(0).createCell(0).setCellValue("Date");
    sheet.createRow(1).createCell(0).setCellFormula("TODAY()+29");
    sheet.createRow(2).createCell(0).setCellFormula("A2+1");
    sheet.createRow(3).createCell(0).setCellFormula("A3+1");
 
    for(int rownum = 1; rownum <= 3; rownum++) sheet.getRow(rownum).getCell(0).setCellStyle(style);
 
    SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
 
    // Condition 1: Formula Is   =A2=A1   (White Font)
    ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("AND(A2-TODAY()>=0,A2-TODAY()<=30)");
    FontFormatting font = rule1.createFontFormatting();
    font.setFontStyle(false, true);
    font.setFontColorIndex(IndexedColors.BLUE.index);
 
    CellRangeAddress[] regions = {
            CellRangeAddress.valueOf("A2:A4")
    };
 
    sheetCF.addConditionalFormatting(regions, rule1);
 
    sheet.getRow(0).createCell(1).setCellValue("Dates within the next 30 days are highlighted");
}
poi-demo-formatting-4

I am ending this apache poi tutorial here to keep the post within a limit.

7. Conclusion

In this tutorial, we learned to read excel, write excel, set and evaluate formula cells, and format the cells with color codings using the Apache POI library.

Happy Learning !!

Source Code on Github

/* ==================================================================== Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the «License»); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an «AS IS» BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ package org.apache.poi.hssf.converter; import java.io.File; import java.io.FileWriter; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.poi.hpsf.SummaryInformation; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFFont; import org.apache.poi.hssf.usermodel.HSSFRichTextString; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.hwpf.converter.HtmlDocumentFacade; import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.util.Beta; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Text; /** * Converts xls files (97-2007) to HTML file. * * @author Sergey Vladimirov (vlsergey {at} gmail {dot} com) */ @Beta public class ExcelToHtmlConverter extends AbstractExcelConverter { private static final POILogger logger = POILogFactory .getLogger( ExcelToHtmlConverter.class ); /** * Java main() interface to interact with {@link ExcelToHtmlConverter} * * <p> * Usage: ExcelToHtmlConverter infile outfile * </p> * Where infile is an input .xls file ( Word 97-2007) which will be rendered * as HTML into outfile */ public static void main( String[] args ) { if ( args.length < 2 ) { System.err .println( «Usage: ExcelToHtmlConverter <inputFile.xls> <saveTo.html>» ); return; } System.out.println( «Converting « + args[0] ); System.out.println( «Saving output to « + args[1] ); try { Document doc = ExcelToHtmlConverter.process( new File( args[0] ) ); FileWriter out = new FileWriter( args[1] ); DOMSource domSource = new DOMSource( doc ); StreamResult streamResult = new StreamResult( out ); TransformerFactory tf = TransformerFactory.newInstance(); Transformer serializer = tf.newTransformer(); // TODO set encoding from a command argument serializer.setOutputProperty( OutputKeys.ENCODING, «UTF-8» ); serializer.setOutputProperty( OutputKeys.INDENT, «no» ); serializer.setOutputProperty( OutputKeys.METHOD, «html» ); serializer.transform( domSource, streamResult ); out.close(); } catch ( Exception e ) { e.printStackTrace(); } } /** * Converts Excel file (97-2007) into HTML file. * * @param xlsFile * file to process * @return DOM representation of result HTML */ public static Document process( File xlsFile ) throws Exception { final HSSFWorkbook workbook = ExcelToHtmlUtils.loadXls( xlsFile ); ExcelToHtmlConverter excelToHtmlConverter = new ExcelToHtmlConverter( DocumentBuilderFactory.newInstance().newDocumentBuilder() .newDocument() ); excelToHtmlConverter.processWorkbook( workbook ); return excelToHtmlConverter.getDocument(); } private String cssClassContainerCell = null; private String cssClassContainerDiv = null; private String cssClassPrefixCell = «c»; private String cssClassPrefixDiv = «d»; private String cssClassPrefixRow = «r»; private String cssClassPrefixTable = «t»; private Map<Short, String> excelStyleToClass = new LinkedHashMap<Short, String>(); private final HtmlDocumentFacade htmlDocumentFacade; private boolean useDivsToSpan = false; public ExcelToHtmlConverter( Document doc ) { htmlDocumentFacade = new HtmlDocumentFacade( doc ); } public ExcelToHtmlConverter( HtmlDocumentFacade htmlDocumentFacade ) { this.htmlDocumentFacade = htmlDocumentFacade; } protected String buildStyle( HSSFWorkbook workbook, HSSFCellStyle cellStyle ) { StringBuilder style = new StringBuilder(); style.append( «white-space:pre-wrap;» ); ExcelToHtmlUtils.appendAlign( style, cellStyle.getAlignment() ); if ( cellStyle.getFillPattern() == 0 ) { // no fill } else if ( cellStyle.getFillPattern() == 1 ) { final HSSFColor foregroundColor = cellStyle .getFillForegroundColorColor(); if ( foregroundColor != null ) style.append( «background-color:» + ExcelToHtmlUtils.getColor( foregroundColor ) + «;» ); } else { final HSSFColor backgroundColor = cellStyle .getFillBackgroundColorColor(); if ( backgroundColor != null ) style.append( «background-color:» + ExcelToHtmlUtils.getColor( backgroundColor ) + «;» ); } buildStyle_border( workbook, style, «top», cellStyle.getBorderTop(), cellStyle.getTopBorderColor() ); buildStyle_border( workbook, style, «right», cellStyle.getBorderRight(), cellStyle.getRightBorderColor() ); buildStyle_border( workbook, style, «bottom», cellStyle.getBorderBottom(), cellStyle.getBottomBorderColor() ); buildStyle_border( workbook, style, «left», cellStyle.getBorderLeft(), cellStyle.getLeftBorderColor() ); HSSFFont font = cellStyle.getFont( workbook ); buildStyle_font( workbook, style, font ); return style.toString(); } private void buildStyle_border( HSSFWorkbook workbook, StringBuilder style, String type, short xlsBorder, short borderColor ) { if ( xlsBorder == HSSFCellStyle.BORDER_NONE ) return; StringBuilder borderStyle = new StringBuilder(); borderStyle.append( ExcelToHtmlUtils.getBorderWidth( xlsBorder ) ); borderStyle.append( ‘ ‘ ); borderStyle.append( ExcelToHtmlUtils.getBorderStyle( xlsBorder ) ); final HSSFColor color = workbook.getCustomPalette().getColor( borderColor ); if ( color != null ) { borderStyle.append( ‘ ‘ ); borderStyle.append( ExcelToHtmlUtils.getColor( color ) ); } style.append( «border-« + type + «:» + borderStyle + «;» ); } void buildStyle_font( HSSFWorkbook workbook, StringBuilder style, HSSFFont font ) { switch ( font.getBoldweight() ) { case HSSFFont.BOLDWEIGHT_BOLD: style.append( «font-weight:bold;» ); break; case HSSFFont.BOLDWEIGHT_NORMAL: // by default, not not increase HTML size // style.append( «font-weight: normal; » ); break; } final HSSFColor fontColor = workbook.getCustomPalette().getColor( font.getColor() ); if ( fontColor != null ) style.append( «color: « + ExcelToHtmlUtils.getColor( fontColor ) + «; « ); if ( font.getFontHeightInPoints() != 0 ) style.append( «font-size:» + font.getFontHeightInPoints() + «pt;» ); if ( font.getItalic() ) { style.append( «font-style:italic;» ); } } public String getCssClassPrefixCell() { return cssClassPrefixCell; } public String getCssClassPrefixDiv() { return cssClassPrefixDiv; } public String getCssClassPrefixRow() { return cssClassPrefixRow; } public String getCssClassPrefixTable() { return cssClassPrefixTable; } public Document getDocument() { return htmlDocumentFacade.getDocument(); } protected String getStyleClassName( HSSFWorkbook workbook, HSSFCellStyle cellStyle ) { final Short cellStyleKey = Short.valueOf( cellStyle.getIndex() ); String knownClass = excelStyleToClass.get( cellStyleKey ); if ( knownClass != null ) return knownClass; String cssStyle = buildStyle( workbook, cellStyle ); String cssClass = htmlDocumentFacade.getOrCreateCssClass( cssClassPrefixCell, cssStyle ); excelStyleToClass.put( cellStyleKey, cssClass ); return cssClass; } public boolean isUseDivsToSpan() { return useDivsToSpan; } protected boolean processCell( HSSFCell cell, Element tableCellElement, int normalWidthPx, int maxSpannedWidthPx, float normalHeightPt ) { final HSSFCellStyle cellStyle = cell.getCellStyle(); String value; switch ( cell.getCellType() ) { case HSSFCell.CELL_TYPE_STRING: // XXX: enrich value = cell.getRichStringCellValue().getString(); break; case HSSFCell.CELL_TYPE_FORMULA: switch ( cell.getCachedFormulaResultType() ) { case HSSFCell.CELL_TYPE_STRING: HSSFRichTextString str = cell.getRichStringCellValue(); if ( str != null && str.length() > 0 ) { value = ( str.toString() ); } else { value = ExcelToHtmlUtils.EMPTY; } break; case HSSFCell.CELL_TYPE_NUMERIC: HSSFCellStyle style = cellStyle; if ( style == null ) { value = String.valueOf( cell.getNumericCellValue() ); } else { value = ( _formatter.formatRawCellContents( cell.getNumericCellValue(), style.getDataFormat(), style.getDataFormatString() ) ); } break; case HSSFCell.CELL_TYPE_BOOLEAN: value = String.valueOf( cell.getBooleanCellValue() ); break; case HSSFCell.CELL_TYPE_ERROR: value = ErrorEval.getText( cell.getErrorCellValue() ); break; default: logger.log( POILogger.WARN, «Unexpected cell cachedFormulaResultType (« + cell.getCachedFormulaResultType() + «)» ); value = ExcelToHtmlUtils.EMPTY; break; } break; case HSSFCell.CELL_TYPE_BLANK: value = ExcelToHtmlUtils.EMPTY; break; case HSSFCell.CELL_TYPE_NUMERIC: value = _formatter.formatCellValue( cell ); break; case HSSFCell.CELL_TYPE_BOOLEAN: value = String.valueOf( cell.getBooleanCellValue() ); break; case HSSFCell.CELL_TYPE_ERROR: value = ErrorEval.getText( cell.getErrorCellValue() ); break; default: logger.log( POILogger.WARN, «Unexpected cell type (« + cell.getCellType() + «)» ); return true; } final boolean noText = ExcelToHtmlUtils.isEmpty( value ); final boolean wrapInDivs = !noText && isUseDivsToSpan() && !cellStyle.getWrapText(); final short cellStyleIndex = cellStyle.getIndex(); if ( cellStyleIndex != 0 ) { HSSFWorkbook workbook = cell.getRow().getSheet().getWorkbook(); String mainCssClass = getStyleClassName( workbook, cellStyle ); if ( wrapInDivs ) { tableCellElement.setAttribute( «class», mainCssClass + » « + cssClassContainerCell ); } else { tableCellElement.setAttribute( «class», mainCssClass ); } if ( noText ) { /* * if cell style is defined (like borders, etc.) but cell text * is empty, add «&nbsp;» to output, so browser won’t collapse * and ignore cell */ value = «u00A0»; } } if ( isOutputLeadingSpacesAsNonBreaking() && value.startsWith( » « ) ) { StringBuilder builder = new StringBuilder(); for ( int c = 0; c < value.length(); c++ ) { if ( value.charAt( c ) != ‘ ‘ ) break; builder.append( ‘u00a0’ ); } if ( value.length() != builder.length() ) builder.append( value.substring( builder.length() ) ); value = builder.toString(); } Text text = htmlDocumentFacade.createText( value ); if ( wrapInDivs ) { Element outerDiv = htmlDocumentFacade.createBlock(); outerDiv.setAttribute( «class», this.cssClassContainerDiv ); Element innerDiv = htmlDocumentFacade.createBlock(); StringBuilder innerDivStyle = new StringBuilder(); innerDivStyle.append( «position:absolute;min-width:» ); innerDivStyle.append( normalWidthPx ); innerDivStyle.append( «px;» ); if ( maxSpannedWidthPx != Integer.MAX_VALUE ) { innerDivStyle.append( «max-width:» ); innerDivStyle.append( maxSpannedWidthPx ); innerDivStyle.append( «px;» ); } innerDivStyle.append( «overflow:hidden;max-height:» ); innerDivStyle.append( normalHeightPt ); innerDivStyle.append( «pt;white-space:nowrap;» ); ExcelToHtmlUtils.appendAlign( innerDivStyle, cellStyle.getAlignment() ); htmlDocumentFacade.addStyleClass( outerDiv, cssClassPrefixDiv, innerDivStyle.toString() ); innerDiv.appendChild( text ); outerDiv.appendChild( innerDiv ); tableCellElement.appendChild( outerDiv ); } else { tableCellElement.appendChild( text ); } return ExcelToHtmlUtils.isEmpty( value ) && cellStyleIndex == 0; } protected void processColumnHeaders( HSSFSheet sheet, int maxSheetColumns, Element table ) { Element tableHeader = htmlDocumentFacade.createTableHeader(); table.appendChild( tableHeader ); Element tr = htmlDocumentFacade.createTableRow(); if ( isOutputRowNumbers() ) { // empty row at left-top corner tr.appendChild( htmlDocumentFacade.createTableHeaderCell() ); } for ( int c = 0; c < maxSheetColumns; c++ ) { if ( !isOutputHiddenColumns() && sheet.isColumnHidden( c ) ) continue; Element th = htmlDocumentFacade.createTableHeaderCell(); String text = getColumnName( c ); th.appendChild( htmlDocumentFacade.createText( text ) ); tr.appendChild( th ); } tableHeader.appendChild( tr ); } /** * Creates COLGROUP element with width specified for all columns. (Except * first if <tt>{@link #isOutputRowNumbers()}==true</tt>) */ protected void processColumnWidths( HSSFSheet sheet, int maxSheetColumns, Element table ) { // draw COLS after we know max column number Element columnGroup = htmlDocumentFacade.createTableColumnGroup(); if ( isOutputRowNumbers() ) { columnGroup.appendChild( htmlDocumentFacade.createTableColumn() ); } for ( int c = 0; c < maxSheetColumns; c++ ) { if ( !isOutputHiddenColumns() && sheet.isColumnHidden( c ) ) continue; Element col = htmlDocumentFacade.createTableColumn(); col.setAttribute( «width», String.valueOf( getColumnWidth( sheet, c ) ) ); columnGroup.appendChild( col ); } table.appendChild( columnGroup ); } protected void processDocumentInformation( SummaryInformation summaryInformation ) { if ( ExcelToHtmlUtils.isNotEmpty( summaryInformation.getTitle() ) ) htmlDocumentFacade.setTitle( summaryInformation.getTitle() ); if ( ExcelToHtmlUtils.isNotEmpty( summaryInformation.getAuthor() ) ) htmlDocumentFacade.addAuthor( summaryInformation.getAuthor() ); if ( ExcelToHtmlUtils.isNotEmpty( summaryInformation.getKeywords() ) ) htmlDocumentFacade.addKeywords( summaryInformation.getKeywords() ); if ( ExcelToHtmlUtils.isNotEmpty( summaryInformation.getComments() ) ) htmlDocumentFacade .addDescription( summaryInformation.getComments() ); } /** * @return maximum 1-base index of column that were rendered, zero if none */ protected int processRow( CellRangeAddress[][] mergedRanges, HSSFRow row, Element tableRowElement ) { final HSSFSheet sheet = row.getSheet(); final short maxColIx = row.getLastCellNum(); if ( maxColIx <= 0 ) return 0; final List<Element> emptyCells = new ArrayList<Element>( maxColIx ); if ( isOutputRowNumbers() ) { Element tableRowNumberCellElement = htmlDocumentFacade .createTableHeaderCell(); processRowNumber( row, tableRowNumberCellElement ); emptyCells.add( tableRowNumberCellElement ); } int maxRenderedColumn = 0; for ( int colIx = 0; colIx < maxColIx; colIx++ ) { if ( !isOutputHiddenColumns() && sheet.isColumnHidden( colIx ) ) continue; CellRangeAddress range = ExcelToHtmlUtils.getMergedRange( mergedRanges, row.getRowNum(), colIx ); if ( range != null && ( range.getFirstColumn() != colIx || range.getFirstRow() != row .getRowNum() ) ) continue; HSSFCell cell = row.getCell( colIx ); int divWidthPx = 0; if ( isUseDivsToSpan() ) { divWidthPx = getColumnWidth( sheet, colIx ); boolean hasBreaks = false; for ( int nextColumnIndex = colIx + 1; nextColumnIndex < maxColIx; nextColumnIndex++ ) { if ( !isOutputHiddenColumns() && sheet.isColumnHidden( nextColumnIndex ) ) continue; if ( row.getCell( nextColumnIndex ) != null && !isTextEmpty( row.getCell( nextColumnIndex ) ) ) { hasBreaks = true; break; } divWidthPx += getColumnWidth( sheet, nextColumnIndex ); } if ( !hasBreaks ) divWidthPx = Integer.MAX_VALUE; } Element tableCellElement = htmlDocumentFacade.createTableCell(); if ( range != null ) { if ( range.getFirstColumn() != range.getLastColumn() ) tableCellElement.setAttribute( «colspan», String.valueOf( range.getLastColumn() — range.getFirstColumn() + 1 ) ); if ( range.getFirstRow() != range.getLastRow() ) tableCellElement.setAttribute( «rowspan», String.valueOf( range.getLastRow() — range.getFirstRow() + 1 ) ); } boolean emptyCell; if ( cell != null ) { emptyCell = processCell( cell, tableCellElement, getColumnWidth( sheet, colIx ), divWidthPx, row.getHeight() / 20f ); } else { emptyCell = true; } if ( emptyCell ) { emptyCells.add( tableCellElement ); } else { for ( Element emptyCellElement : emptyCells ) { tableRowElement.appendChild( emptyCellElement ); } emptyCells.clear(); tableRowElement.appendChild( tableCellElement ); maxRenderedColumn = colIx; } } return maxRenderedColumn + 1; } protected void processRowNumber( HSSFRow row, Element tableRowNumberCellElement ) { tableRowNumberCellElement.setAttribute( «class», «rownumber» ); Text text = htmlDocumentFacade.createText( getRowName( row ) ); tableRowNumberCellElement.appendChild( text ); } protected void processSheet( HSSFSheet sheet ) { processSheetHeader( htmlDocumentFacade.getBody(), sheet ); final int physicalNumberOfRows = sheet.getPhysicalNumberOfRows(); if ( physicalNumberOfRows <= 0 ) return; Element table = htmlDocumentFacade.createTable(); htmlDocumentFacade.addStyleClass( table, cssClassPrefixTable, «border-collapse:collapse;border-spacing:0;» ); Element tableBody = htmlDocumentFacade.createTableBody(); final CellRangeAddress[][] mergedRanges = ExcelToHtmlUtils .buildMergedRangesMap( sheet ); final List<Element> emptyRowElements = new ArrayList<Element>( physicalNumberOfRows ); int maxSheetColumns = 1; for ( int r = sheet.getFirstRowNum(); r <= sheet.getLastRowNum(); r++ ) { HSSFRow row = sheet.getRow( r ); if ( row == null ) continue; if ( !isOutputHiddenRows() && row.getZeroHeight() ) continue; Element tableRowElement = htmlDocumentFacade.createTableRow(); htmlDocumentFacade.addStyleClass( tableRowElement, cssClassPrefixRow, «height:» + ( row.getHeight() / 20f ) + «pt;» ); int maxRowColumnNumber = processRow( mergedRanges, row, tableRowElement ); if ( maxRowColumnNumber == 0 ) { emptyRowElements.add( tableRowElement ); } else { if ( !emptyRowElements.isEmpty() ) { for ( Element emptyRowElement : emptyRowElements ) { tableBody.appendChild( emptyRowElement ); } emptyRowElements.clear(); } tableBody.appendChild( tableRowElement ); } maxSheetColumns = Math.max( maxSheetColumns, maxRowColumnNumber ); } processColumnWidths( sheet, maxSheetColumns, table ); if ( isOutputColumnHeaders() ) { processColumnHeaders( sheet, maxSheetColumns, table ); } table.appendChild( tableBody ); htmlDocumentFacade.getBody().appendChild( table ); } protected void processSheetHeader( Element htmlBody, HSSFSheet sheet ) { Element h2 = htmlDocumentFacade.createHeader2(); h2.appendChild( htmlDocumentFacade.createText( sheet.getSheetName() ) ); htmlBody.appendChild( h2 ); } public void processWorkbook( HSSFWorkbook workbook ) { final SummaryInformation summaryInformation = workbook .getSummaryInformation(); if ( summaryInformation != null ) { processDocumentInformation( summaryInformation ); } if ( isUseDivsToSpan() ) { // prepare CSS classes for later usage this.cssClassContainerCell = htmlDocumentFacade .getOrCreateCssClass( cssClassPrefixCell, «padding:0;margin:0;align:left;vertical-align:top;» ); this.cssClassContainerDiv = htmlDocumentFacade.getOrCreateCssClass( cssClassPrefixDiv, «position:relative;» ); } for ( int s = 0; s < workbook.getNumberOfSheets(); s++ ) { HSSFSheet sheet = workbook.getSheetAt( s ); processSheet( sheet ); } htmlDocumentFacade.updateStylesheet(); } public void setCssClassPrefixCell( String cssClassPrefixCell ) { this.cssClassPrefixCell = cssClassPrefixCell; } public void setCssClassPrefixDiv( String cssClassPrefixDiv ) { this.cssClassPrefixDiv = cssClassPrefixDiv; } public void setCssClassPrefixRow( String cssClassPrefixRow ) { this.cssClassPrefixRow = cssClassPrefixRow; } public void setCssClassPrefixTable( String cssClassPrefixTable ) { this.cssClassPrefixTable = cssClassPrefixTable; } /** * Allows converter to wrap content into two additional DIVs with tricky * styles, so it will wrap across empty cells (like in Excel). * <p> * <b>Warning:</b> after enabling this mode do not serialize result HTML * with INDENT=YES option, because line breaks will make additional * (unwanted) changes */ public void setUseDivsToSpan( boolean useDivsToSpan ) { this.useDivsToSpan = useDivsToSpan; } }

Понравилась статья? Поделить с друзьями:
  • Java parse excel file
  • Java library for excel
  • Java how to read word by word
  • Javascript application vnd ms excel
  • Java excel чтение данных