private void renderCell(
      BandElement bandElement,
      String bandName,
      Object value,
      int gridRow,
      int sheetRow,
      int sheetColumn,
      int rowSpan,
      int colSpan,
      boolean image) {

    if (bandElement instanceof ReportBandElement) {
      colSpan = 1;
    }
    XSSFCellStyle cellStyle =
        buildBandElementStyle(bandElement, value, gridRow, sheetColumn, colSpan);

    // if we have a subreport on the current grid row we have to take care of the sheetColumn
    if (ReportLayout.HEADER_BAND_NAME.equals(bandName)
        && (gridRow == prevSubreportFirstRow)
        && (prevSubreportLastColumn != -1)) {
      sheetColumn = prevSubreportLastColumn - prevSubreportFirstColumn - 1 + sheetColumn;
    }
    XSSFCell c = xlsRow.createCell(sheetColumn);

    if (image) {
      if ((value == null) || "".equals(value)) {
        c.setCellType(XSSFCell.CELL_TYPE_STRING);
        c.setCellValue(wb.getCreationHelper().createRichTextString(IMAGE_NOT_FOUND));
      } else {
        try {
          ImageBandElement ibe = (ImageBandElement) bandElement;
          byte[] imageBytes = getImage((String) value, ibe.getWidth(), ibe.getHeight());
          XSSFClientAnchor anchor =
              new XSSFClientAnchor(
                  0,
                  0,
                  0,
                  0,
                  (short) sheetColumn,
                  sheetRow,
                  (short) (sheetColumn + colSpan),
                  (sheetRow + rowSpan));
          int index = wb.addPicture(imageBytes, XSSFWorkbook.PICTURE_TYPE_JPEG);

          // image is created over the cells, so if it's height is bigger we set the row height
          short height = xlsRow.getHeight();
          int realImageHeight = getRealImageSize((String) value)[1];
          if (ibe.isScaled()) {
            realImageHeight = ibe.getHeight();
          }
          short imageHeight = (short) (realImageHeight * POINTS_FOR_PIXEL / 2.5);
          boolean doResize = false;
          if (imageHeight > height) {
            xlsRow.setHeight(imageHeight);
          } else {
            doResize = true;
          }

          Picture picture = patriarch.createPicture(anchor, index);
          if (doResize) {
            picture.resize();
          }
          anchor.setAnchorType(2);
        } catch (Exception ex) {
          c.setCellType(XSSFCell.CELL_TYPE_STRING);
          c.setCellValue(wb.getCreationHelper().createRichTextString(IMAGE_NOT_LOADED));
        }
      }

      if (cellStyle != null) {
        c.setCellStyle(cellStyle);
      }

    } else {
      if (bandElement instanceof HyperlinkBandElement) {
        Hyperlink hyp = ((HyperlinkBandElement) bandElement).getHyperlink();
        XSSFHyperlink link = wb.getCreationHelper().createHyperlink(XSSFHyperlink.LINK_URL);
        link.setAddress(hyp.getUrl());
        c.setHyperlink(link);
        c.setCellValue(wb.getCreationHelper().createRichTextString(hyp.getText()));
        c.setCellType(XSSFCell.CELL_TYPE_STRING);
      } else if (bandElement instanceof ReportBandElement) {
        Report report = ((ReportBandElement) bandElement).getReport();
        ExporterBean eb = null;
        try {
          eb = getSubreportExporterBean(report, true);
          XlsxExporter subExporter = new XlsxExporter(eb, cellStyle);
          subExporter.export();
          XSSFSheet subreportSheet = subExporter.getSubreportSheet();

          if (ReportLayout.HEADER_BAND_NAME.equals(bandName)
              && (gridRow == prevSubreportFirstRow)) {
            // other subreports on the same header line after the first
            sheetColumn = prevSubreportLastColumn;
            sheetRow -= addedPageRows;
            pageRow -= addedPageRows;
            addedPageRows = 0;
          } else {
            addedPageRows = subreportSheet.getLastRowNum();
            pageRow += addedPageRows;
            // if subreport is not on the first column we merge all cells in the columns before,
            // between the rows subreport occupies
            if (sheetColumn > 0) {
              for (int i = 0; i <= sheetColumn - 1; i++) {
                CellRangeAddress cra = new CellRangeAddress(sheetRow, pageRow, i, i);
                regions.add(new XlsxRegion(cra, null));
              }
            }
          }
          int cols = XlsxUtil.copyToSheet(xlsSheet, sheetRow, sheetColumn, subreportSheet);
          addRegions(xlsSheet, subExporter.getSubreportRegions(), wb);
          if (ReportLayout.HEADER_BAND_NAME.equals(bandName)) {
            prevSubreportFirstRow = gridRow;
            prevSubreportFirstColumn = sheetColumn;
            prevSubreportLastColumn = sheetColumn + cols;
          }
        } catch (Exception e) {
          e.printStackTrace();
        } finally {
          if ((eb != null) && (eb.getResult() != null)) {
            eb.getResult().close();
          }
        }
      } else if (bandElement instanceof ImageColumnBandElement) {
        try {
          ImageColumnBandElement icbe = (ImageColumnBandElement) bandElement;
          String v = StringUtil.getValueAsString(value, null);
          if (StringUtil.BLOB.equals(v)) {
            c.setCellType(XSSFCell.CELL_TYPE_STRING);
            c.setCellValue(wb.getCreationHelper().createRichTextString(StringUtil.BLOB));
          } else {
            byte[] imageD = StringUtil.decodeImage(v);
            byte[] imageBytes = getImage(imageD, icbe.getWidth(), icbe.getHeight());
            XSSFClientAnchor anchor =
                new XSSFClientAnchor(
                    0,
                    0,
                    0,
                    0,
                    (short) sheetColumn,
                    sheetRow,
                    (short) (sheetColumn + colSpan),
                    (sheetRow + rowSpan));
            int index = wb.addPicture(imageBytes, XSSFWorkbook.PICTURE_TYPE_JPEG);

            // image is created over the cells, so if it's height is bigger we set the row height
            short height = xlsRow.getHeight();
            int realImageHeight = getRealImageSize(imageBytes)[1];
            if (icbe.isScaled()) {
              realImageHeight = icbe.getHeight();
            }
            short imageHeight = (short) (realImageHeight * POINTS_FOR_PIXEL / 2.5);
            if (imageHeight > height) {
              xlsRow.setHeight(imageHeight);
            }

            Picture picture = patriarch.createPicture(anchor, index);
            picture.resize();
            anchor.setAnchorType(2);
          }
        } catch (Exception e) {
          e.printStackTrace();
          c.setCellType(XSSFCell.CELL_TYPE_STRING);
          c.setCellValue(wb.getCreationHelper().createRichTextString(IMAGE_NOT_LOADED));
        }

      } else {

        if (value == null) {
          c.setCellType(XSSFCell.CELL_TYPE_STRING);
          c.setCellValue(wb.getCreationHelper().createRichTextString(""));
        } else if (value instanceof Number) {
          c.setCellType(XSSFCell.CELL_TYPE_NUMERIC);
          c.setCellValue(((Number) value).doubleValue());
        } else {
          String pattern = null;
          if (bandElement instanceof FieldBandElement) {
            FieldBandElement fbe = (FieldBandElement) bandElement;
            pattern = fbe.getPattern();
          }
          if ((value instanceof java.sql.Date) || (value instanceof java.sql.Timestamp)) {
            Date date;
            if (value instanceof java.sql.Date) {
              date = new Date(((java.sql.Date) value).getTime());
            } else {
              date = (java.sql.Timestamp) value;
            }
            if (cellStyle != null) {
              if (pattern == null) {
                // use default pattern if none selected
                Locale locale = Locale.getDefault();
                pattern =
                    ((SimpleDateFormat) DateFormat.getDateInstance(SimpleDateFormat.MEDIUM, locale))
                        .toPattern();
              } else {
                pattern = StringUtil.getI18nString(pattern, getReportLanguage());
              }
              cellStyle.setDataFormat(wb.createDataFormat().getFormat(pattern));
            }
            c.setCellValue(date);
          } else {
            c.setCellType(XSSFCell.CELL_TYPE_STRING);
            String text = StringUtil.getValueAsString(value, pattern);
            if ((bandElement != null) && bandElement.isWrapText()) {
              // try to interpret new line characters
              // \\n is used here to be possible to add in designer grid cell with \n
              if (text.contains("\\n")
                  || text.contains("\n")
                  || text.contains("\r")
                  || text.contains("\r\n")) {
                String crLf = Character.toString((char) 13) + Character.toString((char) 10);
                int lines = countLines(text);
                if (text.contains("\r\n")) {
                  text = text.replaceAll("\r\n", crLf);
                } else {
                  text = text.replaceAll("(\n)|(\r)|(\\\\n)", crLf);
                }
                c.setCellValue(text);
                cellStyle.setWrapText(true);
                xlsRow.setHeightInPoints(lines * (cellStyle.getFont().getFontHeightInPoints() + 3));
              } else {
                c.setCellValue(wb.getCreationHelper().createRichTextString(text));
              }
            } else {
              c.setCellValue(wb.getCreationHelper().createRichTextString(text));
            }
          }
        }
      }

      if (cellStyle != null) {
        if (bandElement != null) {
          cellStyle.setRotation(bandElement.getTextRotation());
        }
        if (!(bandElement instanceof ReportBandElement)) {
          c.setCellStyle(cellStyle);
        }
      }

      if ((rowSpan > 1) || (colSpan > 1)) {
        CellRangeAddress cra =
            new CellRangeAddress(
                sheetRow, sheetRow + rowSpan - 1, sheetColumn, sheetColumn + colSpan - 1);
        Border beBorder = bandElement.getBorder();
        if (hasRowRenderConditions(bandElement, gridRow, value)) {
          // for row render conditions we must keep the row border
          beBorder = border;
        }
        regions.add(new XlsxRegion(cra, beBorder));
      }
    }
  }
  private void renderDocxCell(
      String bandName,
      BandElement bandElement,
      Object value,
      int gridRow,
      int rowSpan,
      int colSpan,
      boolean image,
      int column) {
    Map<String, Object> style = buildCellStyleMap(bandElement, value, gridRow, column, colSpan);

    String verticalMergedVal = null;
    if (rowSpan > 1) {
      verticalMergedVal = "restart";
      rowSpanForColumn.put(column, rowSpan);
    } else {
      int span = rowSpanForColumn.get(column);
      if (span > 1) {
        rowSpanForColumn.put(column, span - 1);
        if (span == 2) {
          // last cell to merge vertically
          verticalMergedVal = "close";
        } else {
          verticalMergedVal = "";
        }
      }
    }

    int width = headerwidths[column];
    if (colSpan > 1) {
      for (int i = 1; i < colSpan; i++) {
        width += headerwidths[column + i];
      }
    }

    if (image) {
      if (value == null) {
        addTableCell(tableRow, bandElement, "", width, style, colSpan, verticalMergedVal);
      } else {
        ImageBandElement ibe = (ImageBandElement) bandElement;
        P pImage;
        try {
          byte[] imageD = getImage((String) value);
          byte[] imageBytes = getImage(imageD, ibe.getWidth(), ibe.getHeight());
          int imageW;
          if (ibe.getWidth() == null) {
            imageW = getRealImageSize(imageBytes)[0];
          } else {
            imageW = ibe.getWidth();
          }
          pImage = newImage(wordMLPackage, imageBytes, null, null, 0, 1, pixelsToDxa(imageW));
          addTableCell(
              tableRow, bandElement, pImage, width, style, colSpan, verticalMergedVal, true);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    } else if (bandElement instanceof HyperlinkBandElement) {
      Hyperlink hyperlink = ((HyperlinkBandElement) bandElement).getHyperlink();
      addHyperlinkTableCell(
          tableRow, bandElement, hyperlink, width, style, colSpan, verticalMergedVal);

    } else if (bandElement instanceof ReportBandElement) {
      Report report = ((ReportBandElement) bandElement).getReport();
      ExporterBean eb = null;
      try {
        eb = getSubreportExporterBean(report);
        DocxExporter subExporter = new DocxExporter(eb, width);
        subExporter.export();
        Tbl innerTable = subExporter.getTable();
        addSubreportTableCell(
            tableRow, bandElement, innerTable, width, style, colSpan, verticalMergedVal);
      } catch (Exception e) {
        addTableCell(tableRow, bandElement, "", width, style, colSpan, verticalMergedVal);
        e.printStackTrace();
      } finally {
        if ((eb != null) && (eb.getResult() != null)) {
          eb.getResult().close();
        }
      }
    } else if (((bandElement instanceof VariableBandElement)
            && (VariableFactory.getVariable(((VariableBandElement) bandElement).getVariable())
                instanceof PageNoVariable))
        || ((bandElement instanceof ExpressionBandElement)
            && ((ExpressionBandElement) bandElement)
                .getExpression()
                .contains(PageNoVariable.PAGE_NO_PARAM))) {

      // limitation: if header or footer contains PAGE_NO varaible, only this will be shown,
      // all other cells from header/footer will be ignored
      if (ReportLayout.PAGE_HEADER_BAND_NAME.equals(bandName)) {
        hasPageNoHeader = true;
      } else if (ReportLayout.PAGE_FOOTER_BAND_NAME.equals(bandName)) {
        hasPageNoFooter = true;
      }
      // does not work (we should add pageNo to header or footer directly and not inside a table
      // P numP = createPageNumParagraph();
      // addTableCell(tableRow, bandElement, bandElement.getText(), numP, width, style, colSpan,
      // verticalMergedVal);

    } else if (bandElement instanceof ImageColumnBandElement) {
      try {
        String v = StringUtil.getValueAsString(value, null);
        if (StringUtil.BLOB.equals(v)) {
          addTableCell(
              tableRow, bandElement, StringUtil.BLOB, width, style, colSpan, verticalMergedVal);
        } else {
          ImageColumnBandElement icbe = (ImageColumnBandElement) bandElement;
          byte[] imageD = StringUtil.decodeImage(v);
          byte[] imageBytes = getImage(imageD, icbe.getWidth(), icbe.getHeight());
          int imageW;
          if (icbe.getWidth() == null) {
            imageW = getRealImageSize(imageBytes)[0];
          } else {
            imageW = icbe.getWidth();
          }
          P pImage = newImage(wordMLPackage, imageBytes, null, null, 0, 1, pixelsToDxa(imageW));
          addTableCell(
              tableRow, bandElement, pImage, width, style, colSpan, verticalMergedVal, true);
        }
      } catch (Exception e) {
        e.printStackTrace();
        addTableCell(
            tableRow, bandElement, IMAGE_NOT_LOADED, width, style, colSpan, verticalMergedVal);
      }
    } else {
      String stringValue;
      if (style.containsKey(StyleFormatConstants.PATTERN)) {
        stringValue =
            StringUtil.getValueAsString(
                value, (String) style.get(StyleFormatConstants.PATTERN), getReportLanguage());
      } else {
        stringValue = StringUtil.getValueAsString(value, null, getReportLanguage());
      }
      if (stringValue == null) {
        stringValue = "";
      }
      addTableCell(tableRow, bandElement, stringValue, width, style, colSpan, verticalMergedVal);
    }
  }