// http://poi.apache.org/apidocs/org/apache/poi/xssf/usermodel/extensions/XSSFHeaderFooter.html
  private void renderCellToHeaderFooter(
      StringBuilder result,
      String bandName,
      BandElement bandElement,
      Object value,
      int gridRow,
      int row,
      int column,
      int cols,
      int rowSpan,
      int colSpan,
      boolean isImage) {

    if (newRow) {
      result.append("\r\n ");
    } else {
      result.append(" ");
    }
    boolean specialCell = false;
    if (bandElement instanceof VariableBandElement) {
      VariableBandElement vbe = (VariableBandElement) bandElement;
      Variable var = VariableFactory.getVariable(vbe.getVariable());
      if (var instanceof PageNoVariable) {
        specialCell = true;
        result.append("&P");
      }
    } else if (bandElement instanceof ExpressionBandElement) {
      // special case pageNo inside an expression
      // bandName is not important here (it is used for groupRow computation)
      PrefixSuffix pf = interpretPageNo(bandElement);
      if (pf != null) {
        result.append(pf.getPrefix()).append(" &P ").append(pf.getSuffix());
        specialCell = true;
      }
    }
    if (!specialCell) {
      result.append(value);
    }
  }
  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);
    }
  }