/* ====================================================================
   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 static org.apache.poi.hssf.converter.AbstractExcelUtils.buildMergedRangesMap;
import static org.apache.poi.hssf.converter.AbstractExcelUtils.getAlign;
import static org.apache.poi.hssf.converter.AbstractExcelUtils.getBorderStyle;
import static org.apache.poi.hssf.converter.AbstractExcelUtils.getBorderWidth;
import static org.apache.poi.hssf.converter.AbstractExcelUtils.getColor;
import static org.apache.poi.hssf.converter.AbstractExcelUtils.getMergedRange;
import static org.apache.poi.hssf.converter.AbstractExcelUtils.isEmpty;
import static org.apache.poi.hssf.converter.AbstractExcelUtils.isNotEmpty;
import static org.apache.poi.hssf.converter.AbstractExcelUtils.loadXls;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.xml.transform.Transformer;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
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.FoDocumentFacade;
import org.apache.poi.hwpf.converter.FontReplacer.Triplet;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.Beta;
import org.apache.poi.util.XMLHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;

/**
 * Converts xls files (97-2007) to XSL FO.
 */
@Beta
public class ExcelToFoConverter extends AbstractExcelConverter {
    private static final float CM_PER_INCH = 2.54f;

    private static final float DPI = 72;

    private static final Logger LOG = LogManager.getLogger(ExcelToFoConverter.class);

    private static final float PAPER_A4_HEIGHT_INCHES = 29.4f / CM_PER_INCH;

    private static final float PAPER_A4_WIDTH_INCHES = 21.0f / CM_PER_INCH;

    /**
     * Usage: ExcelToHtmlConverter infile outfile
     * <p>
     * Where infile is an input .xls file ( Word 97-2007) which will be rendered
     * as XSL FO into outfile
     */
    public static void main(String[] args) throws Exception {
        if (args.length < 2) {
            System.err.println("Usage: ExcelToFoConverter <inputFile.xls> <saveTo.xml>");
            return;
        }

        System.out.println("Converting " + args[0]);
        System.out.println("Saving output to " + args[1]);

        Document doc = ExcelToHtmlConverter.process(new File(args[0]));

        DOMSource domSource = new DOMSource(doc);
        StreamResult streamResult = new StreamResult(new File(args[1]));

        // TODO set encoding from a command argument
        Transformer serializer = XMLHelper.newTransformer();
        serializer.transform(domSource, streamResult);
    }

    /**
     * Converts Excel file (97-2007) into XSL FO file.
     *
     * @param xlsFile file to process
     * @return DOM representation of result XSL FO
     */
    public static Document process(File xlsFile) throws Exception {
        try (HSSFWorkbook workbook = loadXls(xlsFile)) {
            ExcelToFoConverter excelToHtmlConverter = new ExcelToFoConverter(
                XMLHelper.newDocumentBuilder().newDocument());
            excelToHtmlConverter.processWorkbook(workbook);
            return excelToHtmlConverter.getDocument();
        }
    }

    private final FoDocumentFacade foDocumentFacade;

    private float pageMarginInches = 0.4f;

    public ExcelToFoConverter(Document document) {
        this.foDocumentFacade = new FoDocumentFacade(document);
    }

    public ExcelToFoConverter(FoDocumentFacade foDocumentFacade) {
        this.foDocumentFacade = foDocumentFacade;
    }

    protected String createPageMaster(float tableWidthIn, String pageMasterName) {
        final float paperHeightIn;
        final float paperWidthIn;
        {
            float requiredWidthIn = tableWidthIn + 2 * getPageMarginInches();

            if (requiredWidthIn < PAPER_A4_WIDTH_INCHES) {
                // portrait orientation
                paperWidthIn = PAPER_A4_WIDTH_INCHES;
                paperHeightIn = PAPER_A4_HEIGHT_INCHES;
            } else {
                // landscape orientation
                paperWidthIn = requiredWidthIn;
                paperHeightIn = paperWidthIn
                    * (PAPER_A4_WIDTH_INCHES / PAPER_A4_HEIGHT_INCHES);
            }
        }

        final float leftMargin = getPageMarginInches();
        final float rightMargin = getPageMarginInches();
        final float topMargin = getPageMarginInches();
        final float bottomMargin = getPageMarginInches();

        Element pageMaster = foDocumentFacade
            .addSimplePageMaster(pageMasterName);
        pageMaster.setAttribute("page-height", paperHeightIn + "in");
        pageMaster.setAttribute("page-width", paperWidthIn + "in");

        Element regionBody = foDocumentFacade.addRegionBody(pageMaster);
        regionBody.setAttribute("margin", topMargin + "in " + rightMargin
            + "in " + bottomMargin + "in " + leftMargin + "in");

        return pageMasterName;
    }

    @Override
    protected Document getDocument() {
        return foDocumentFacade.getDocument();
    }

    public float getPageMarginInches() {
        return pageMarginInches;
    }

    /**
     * Returns <tt>false</tt> if cell style by itself (without text, i.e.
     * borders, fill, etc.) worth a mention, <tt>true</tt> otherwise
     *
     * @return <tt>false</tt> if cell style by itself (without text, i.e.
     * borders, fill, etc.) worth a mention, <tt>true</tt> otherwise
     */
    protected boolean isEmptyStyle(CellStyle cellStyle) {
        return cellStyle == null || (
            cellStyle.getFillPattern() == FillPatternType.NO_FILL
                && cellStyle.getBorderTop() == BorderStyle.NONE
                && cellStyle.getBorderRight() == BorderStyle.NONE
                && cellStyle.getBorderBottom() == BorderStyle.NONE
                && cellStyle.getBorderLeft() == BorderStyle.NONE
        );
    }

    protected boolean processCell(HSSFWorkbook workbook, HSSFCell cell,
        Element tableCellElement, int normalWidthPx, int maxSpannedWidthPx,
        float normalHeightPt) {
        final HSSFCellStyle cellStyle = cell.getCellStyle();

        String value;
        switch (cell.getCellType()) {
            case STRING:
                // XXX: enrich
                value = cell.getRichStringCellValue().getString();
                break;
            case FORMULA:
                switch (cell.getCachedFormulaResultType()) {
                    case STRING:
                        HSSFRichTextString str = cell.getRichStringCellValue();
                        if (str != null && str.length() > 0) {
                            value = (str.toString());
                        } else {
                            value = AbstractExcelUtils.EMPTY;
                        }
                        break;
                    case NUMERIC:
                        double nValue = cell.getNumericCellValue();
                        short df = cellStyle.getDataFormat();
                        String dfs = cellStyle.getDataFormatString();
                        value = _formatter.formatRawCellContents(nValue, df, dfs);
                        break;
                    case BOOLEAN:
                        value = Boolean.toString(cell.getBooleanCellValue());
                        break;
                    case ERROR:
                        value = ErrorEval.getText(cell.getErrorCellValue());
                        break;
                    default:
                        LOG.atWarn().log("Unexpected cell cachedFormulaResultType ({})", cell.getCachedFormulaResultType());
                        value = AbstractExcelUtils.EMPTY;
                        break;
                }
                break;
            case BLANK:
                value = AbstractExcelUtils.EMPTY;
                break;
            case NUMERIC:
                value = _formatter.formatCellValue(cell);
                break;
            case BOOLEAN:
                value = Boolean.toString(cell.getBooleanCellValue());
                break;
            case ERROR:
                value = ErrorEval.getText(cell.getErrorCellValue());
                break;
            default:
                LOG.atWarn().log("Unexpected cell type ({})", cell.getCellType());
                return true;
        }

        final boolean noText = isEmpty(value);
        final boolean wrapInDivs = !noText && !cellStyle.getWrapText();

        final boolean emptyStyle = isEmptyStyle(cellStyle);
        if (!emptyStyle && 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 = foDocumentFacade.createText(value);
        Element block = foDocumentFacade.createBlock();

        if (wrapInDivs) {
            block.setAttribute("absolute-position", "fixed");
            block.setAttribute("left", "0px");
            block.setAttribute("top", "0px");
            block.setAttribute("bottom", "0px");
            block.setAttribute("min-width", normalWidthPx + "px");

            if (maxSpannedWidthPx != Integer.MAX_VALUE) {
                block.setAttribute("max-width", maxSpannedWidthPx + "px");
            }

            block.setAttribute("overflow", "hidden");
            block.setAttribute("height", normalHeightPt + "pt");
            block.setAttribute("keep-together.within-line", "always");
            block.setAttribute("wrap-option", "no-wrap");
        }

        processCellStyle(workbook, cell.getCellStyle(), tableCellElement,
            block);

        block.appendChild(text);
        tableCellElement.appendChild(block);

        return isEmpty(value) && emptyStyle;
    }

    protected void processCellStyle(HSSFWorkbook workbook,
        HSSFCellStyle cellStyle, Element cellTarget, Element blockTarget) {
        blockTarget.setAttribute("white-space-collapse", "false");
        {
            String textAlign = getAlign(cellStyle.getAlignment());
            if (isNotEmpty(textAlign)) {
                blockTarget.setAttribute("text-align", textAlign);
            }
        }

        if (cellStyle.getFillPattern() == FillPatternType.NO_FILL) {
            // no fill
        } else if (cellStyle.getFillPattern() == FillPatternType.SOLID_FOREGROUND) {
            final HSSFColor foregroundColor = cellStyle
                .getFillForegroundColorColor();
            if (foregroundColor != null) {
                cellTarget.setAttribute("background-color",
                    getColor(foregroundColor));
            }
        } else {
            final HSSFColor backgroundColor = cellStyle
                .getFillBackgroundColorColor();
            if (backgroundColor != null) {
                cellTarget.setAttribute("background-color",
                    getColor(backgroundColor));
            }
        }

        processCellStyleBorder(workbook, cellTarget, "top",
            cellStyle.getBorderTop(), cellStyle.getTopBorderColor());
        processCellStyleBorder(workbook, cellTarget, "right",
            cellStyle.getBorderRight(), cellStyle.getRightBorderColor());
        processCellStyleBorder(workbook, cellTarget, "bottom",
            cellStyle.getBorderBottom(), cellStyle.getBottomBorderColor());
        processCellStyleBorder(workbook, cellTarget, "left",
            cellStyle.getBorderLeft(), cellStyle.getLeftBorderColor());

        HSSFFont font = cellStyle.getFont(workbook);
        processCellStyleFont(workbook, blockTarget, font);

    }

    protected void processCellStyleBorder(HSSFWorkbook workbook,
        Element cellTarget, String type, BorderStyle xlsBorder, short borderColor) {
        if (xlsBorder == BorderStyle.NONE) {
            return;
        }

        StringBuilder borderStyle = new StringBuilder();
        borderStyle.append(getBorderWidth(xlsBorder));

        final HSSFColor color = workbook.getCustomPalette().getColor(
            borderColor);
        if (color != null) {
            borderStyle.append(' ');
            borderStyle.append(getColor(color));

            borderStyle.append(' ');
            borderStyle.append(getBorderStyle(xlsBorder));
        }

        cellTarget.setAttribute("border-" + type, borderStyle.toString());
    }

    protected void processCellStyleFont(HSSFWorkbook workbook,
        Element blockTarget, HSSFFont font) {
        Triplet triplet = new Triplet();
        triplet.fontName = font.getFontName();
        triplet.bold = font.getBold();
        triplet.italic = font.getItalic();

        getFontReplacer().update(triplet);
        setBlockProperties(blockTarget, triplet);

        final HSSFColor fontColor = workbook.getCustomPalette().getColor(
            font.getColor());
        if (fontColor != null) {
            blockTarget.setAttribute("color",
                getColor(fontColor));
        }

        if (font.getFontHeightInPoints() != 0) {
            blockTarget.setAttribute("font-size", font.getFontHeightInPoints()
                + "pt");
        }

    }

    protected void processColumnHeaders(HSSFSheet sheet, int maxSheetColumns,
        Element table) {
        Element tableHeader = foDocumentFacade.createTableHeader();
        Element row = foDocumentFacade.createTableRow();

        if (isOutputRowNumbers()) {
            // empty cell at left-top corner
            final Element tableCellElement = foDocumentFacade.createTableCell();
            tableCellElement.appendChild(foDocumentFacade.createBlock());
            row.appendChild(tableCellElement);
        }

        for (int c = 0; c < maxSheetColumns; c++) {
            if (!isOutputHiddenColumns() && sheet.isColumnHidden(c)) {
                continue;
            }

            Element cell = foDocumentFacade.createTableCell();
            Element block = foDocumentFacade.createBlock();
            block.setAttribute("text-align", "center");
            block.setAttribute("font-weight", "bold");

            String text = getColumnName(c);
            block.appendChild(foDocumentFacade.createText(text));

            cell.appendChild(block);
            row.appendChild(cell);
        }

        tableHeader.appendChild(row);
        table.appendChild(tableHeader);
    }

    /**
     * Creates COLGROUP element with width specified for all columns. (Except
     * first if <tt>{@link #isOutputRowNumbers()}==true</tt>)
     *
     * @return table width in inches
     */
    protected float processColumnWidths(HSSFSheet sheet, int maxSheetColumns,
        Element table) {
        float tableWidth = 0;

        if (isOutputRowNumbers()) {
            final float columnWidthIn = getDefaultColumnWidth(sheet) / DPI;

            final Element rowNumberColumn = foDocumentFacade
                .createTableColumn();
            rowNumberColumn.setAttribute("column-width", columnWidthIn + "in");
            table.appendChild(rowNumberColumn);

            tableWidth += columnWidthIn;
        }

        for (int c = 0; c < maxSheetColumns; c++) {
            if (!isOutputHiddenColumns() && sheet.isColumnHidden(c)) {
                continue;
            }

            final float columnWidthIn = getColumnWidth(sheet, c) / DPI;

            Element col = foDocumentFacade.createTableColumn();
            col.setAttribute("column-width", columnWidthIn + "in");
            table.appendChild(col);

            tableWidth += columnWidthIn;
        }

        table.setAttribute("width", tableWidth + "in");
        return tableWidth;
    }

    protected void processDocumentInformation(
        SummaryInformation summaryInformation) {
        if (isNotEmpty(summaryInformation.getTitle())) {
            foDocumentFacade.setTitle(summaryInformation.getTitle());
        }

        if (isNotEmpty(summaryInformation.getAuthor())) {
            foDocumentFacade.setCreator(summaryInformation.getAuthor());
        }

        if (isNotEmpty(summaryInformation.getKeywords())) {
            foDocumentFacade.setKeywords(summaryInformation.getKeywords());
        }

        if (isNotEmpty(summaryInformation.getComments())) {
            foDocumentFacade.setDescription(summaryInformation.getComments());
        }
    }

    /**
     * @return maximum 1-base index of column that were rendered, zero if none
     */
    protected int processRow(HSSFWorkbook workbook,
        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<>(maxColIx);

        if (isOutputRowNumbers()) {
            Element tableRowNumberCellElement = processRowNumber(row);
            emptyCells.add(tableRowNumberCellElement);
        }

        int maxRenderedColumn = 0;
        for (int colIx = 0; colIx < maxColIx; colIx++) {
            if (!isOutputHiddenColumns() && sheet.isColumnHidden(colIx)) {
                continue;
            }

            CellRangeAddress range = getMergedRange(mergedRanges, row.getRowNum(), colIx);

            if (range != null
                && (range.getFirstColumn() != colIx || range.getFirstRow() != row
                .getRowNum())) {
                continue;
            }

            HSSFCell cell = row.getCell(colIx);

            // spanning using overlapping blocks
            int divWidthPx = 0;
            {
                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 = foDocumentFacade.createTableCell();

            if (range != null) {
                if (range.getFirstColumn() != range.getLastColumn()) {
                    tableCellElement.setAttribute(
                        "number-columns-spanned",
                        String.valueOf(range.getLastColumn()
                            - range.getFirstColumn() + 1));
                }
                if (range.getFirstRow() != range.getLastRow()) {
                    tableCellElement.setAttribute(
                        "number-rows-spanned",
                        String.valueOf(range.getLastRow()
                            - range.getFirstRow() + 1));
                }
            }

            boolean emptyCell;
            if (cell != null) {
                emptyCell = processCell(workbook, cell, tableCellElement,
                    getColumnWidth(sheet, colIx), divWidthPx,
                    row.getHeight() / 20f);
            } else {
                tableCellElement.appendChild(foDocumentFacade.createBlock());
                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 Element processRowNumber(HSSFRow row) {
        Element tableRowNumberCellElement = foDocumentFacade.createTableCell();

        Element block = foDocumentFacade.createBlock();
        block.setAttribute("text-align", "right");
        block.setAttribute("font-weight", "bold");

        Text text = foDocumentFacade.createText(getRowName(row));
        block.appendChild(text);

        tableRowNumberCellElement.appendChild(block);
        return tableRowNumberCellElement;
    }

    protected float processSheet(HSSFWorkbook workbook, HSSFSheet sheet,
        Element flow) {
        final int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();
        if (physicalNumberOfRows <= 0) {
            return 0;
        }

        processSheetName(sheet, flow);

        Element table = foDocumentFacade.createTable();
        table.setAttribute("table-layout", "fixed");

        Element tableBody = foDocumentFacade.createTableBody();

        final CellRangeAddress[][] mergedRanges = buildMergedRangesMap(sheet);

        final List<Element> emptyRowElements = new ArrayList<>(
            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 = foDocumentFacade.createTableRow();
            tableRowElement.setAttribute("height", row.getHeight() / 20f
                + "pt");

            int maxRowColumnNumber = processRow(workbook, mergedRanges, row,
                tableRowElement);

            if (tableRowElement.getChildNodes().getLength() == 0) {
                Element emptyCellElement = foDocumentFacade.createTableCell();
                emptyCellElement.appendChild(foDocumentFacade.createBlock());
                tableRowElement.appendChild(emptyCellElement);
            }

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

        float tableWidthIn = processColumnWidths(sheet, maxSheetColumns, table);

        if (isOutputColumnHeaders()) {
            processColumnHeaders(sheet, maxSheetColumns, table);
        }

        table.appendChild(tableBody);
        flow.appendChild(table);

        return tableWidthIn;
    }

    /**
     * Process single sheet (as specified by 0-based sheet index)
     *
     * @return <tt>true</tt> if result were added to FO document, <tt>false</tt>
     * otherwise
     */
    protected boolean processSheet(HSSFWorkbook workbook, int sheetIndex) {
        String pageMasterName = "sheet-" + sheetIndex;

        Element pageSequence = foDocumentFacade
            .createPageSequence(pageMasterName);
        Element flow = foDocumentFacade.addFlowToPageSequence(pageSequence,
            "xsl-region-body");

        HSSFSheet sheet = workbook.getSheetAt(sheetIndex);
        float tableWidthIn = processSheet(workbook, sheet, flow);

        if (tableWidthIn == 0) {
            return false;
        }

        createPageMaster(tableWidthIn, pageMasterName);
        foDocumentFacade.addPageSequence(pageSequence);
        return true;
    }

    protected void processSheetName(HSSFSheet sheet, Element flow) {
        Element titleBlock = foDocumentFacade.createBlock();

        Triplet triplet = new Triplet();
        triplet.bold = true;
        triplet.italic = false;
        triplet.fontName = "Arial";
        getFontReplacer().update(triplet);

        setBlockProperties(titleBlock, triplet);
        titleBlock.setAttribute("font-size", "200%");

        Element titleInline = foDocumentFacade.createInline();
        titleInline.appendChild(foDocumentFacade.createText(sheet
            .getSheetName()));
        titleBlock.appendChild(titleInline);
        flow.appendChild(titleBlock);

        Element titleBlock2 = foDocumentFacade.createBlock();
        Element titleInline2 = foDocumentFacade.createInline();
        titleBlock2.appendChild(titleInline2);
        flow.appendChild(titleBlock2);
    }

    public void processWorkbook(HSSFWorkbook workbook) {
        final SummaryInformation summaryInformation = workbook
            .getSummaryInformation();
        if (summaryInformation != null) {
            processDocumentInformation(summaryInformation);
        }

        for (int s = 0; s < workbook.getNumberOfSheets(); s++) {
            processSheet(workbook, s);
        }
    }

    private void setBlockProperties(Element textBlock, Triplet triplet) {
        if (triplet.bold) {
            textBlock.setAttribute("font-weight", "bold");
        }

        if (triplet.italic) {
            textBlock.setAttribute("font-style", "italic");
        }

        if (isNotEmpty(triplet.fontName)) {
            textBlock.setAttribute("font-family", triplet.fontName);
        }
    }

    public void setPageMarginInches(float pageMarginInches) {
        this.pageMarginInches = pageMarginInches;
    }

}
