public void writeDataToExcel(Sheet sheet) {
    LOGGER.debug("[{}] Exporting data to excel", getText());

    List<ExcelColumnRenderer> columnRendererList = new ArrayList<>();
    columnRendererList.add(new TaskStatusExcelColumn());
    columnRendererList.add(new TaskDescriptionExcelColumn());

    TimerangeProvider timerangeProvider = fetchTimereportContext.get().getTimerangeProvider();
    LocalDate startDate = timerangeProvider.getStartDate();
    LocalDate endDate = timerangeProvider.getEndDate();

    long amountOfDaysToDisplay = ChronoUnit.DAYS.between(startDate, endDate);
    for (int days = 0; days <= amountOfDaysToDisplay; days++) {
      LocalDate currentColumnDate = timerangeProvider.getStartDate().plus(days, ChronoUnit.DAYS);
      String displayDate = FormattingUtil.formatDate(currentColumnDate);
      columnRendererList.add(new WorklogExcelColumn(displayDate, currentColumnDate));
    }

    columnRendererList.add(new TaskWorklogSummaryExcelColumn());

    TreeItem<DisplayRow> root = taskTableView.getRoot();
    ObservableList<TreeItem<DisplayRow>> children = root.getChildren();

    for (int columnIndex = 0; columnIndex < columnRendererList.size(); columnIndex++) {
      ExcelColumnRenderer excelColumnRenderer = columnRendererList.get(columnIndex);
      excelColumnRenderer.renderCells(
          columnIndex,
          sheet,
          children,
          fetchTimereportContext.get().getGroupByCategory().isPresent());
    }

    // autosize column widths
    for (int i = 0; i < columnRendererList.size(); i++) {
      sheet.autoSizeColumn(i);
    }
  }
  public void assignSampleData(FXOMObject startObject) {
    assert startObject != null;

    final Object sceneGraphObject = startObject.getSceneGraphObject();
    final AbstractSampleData currentData = sampleDataMap.get(startObject);
    final AbstractSampleData newData;

    if (sceneGraphObject == null) {
      // startObject is unresolved
      newData = null;
    } else {
      final Class<?> sceneGraphClass = sceneGraphObject.getClass();
      if (sceneGraphClass == ChoiceBox.class) {
        final ChoiceBox<?> choiceBox = (ChoiceBox) sceneGraphObject;
        if (choiceBox.getItems().isEmpty()) {
          if (currentData instanceof ChoiceBoxSampleData) {
            newData = currentData;
          } else {
            newData = new ChoiceBoxSampleData();
          }
        } else {
          newData = null;
        }
      } else if (sceneGraphClass == ComboBox.class) {
        final ComboBox<?> comboBox = (ComboBox) sceneGraphObject;
        if (comboBox.getItems().isEmpty()) {
          if (currentData instanceof ComboBoxSampleData) {
            newData = currentData;
          } else {
            newData = new ComboBoxSampleData();
          }
        } else {
          newData = null;
        }
      } else if (sceneGraphClass == ListView.class) {
        final ListView<?> listView = (ListView) sceneGraphObject;
        if (listView.getItems().isEmpty()) {
          if (currentData instanceof ListViewSampleData) {
            newData = currentData;
          } else {
            newData = new ListViewSampleData();
          }
        } else {
          newData = null;
        }
      } else if (sceneGraphClass == TreeView.class) {
        final TreeView<?> treeView = (TreeView) sceneGraphObject;
        if (treeView.getRoot() == null) {
          if (currentData instanceof TreeViewSampleData) {
            newData = currentData;
          } else {
            newData = new TreeViewSampleData();
          }
        } else {
          newData = null;
        }
      } else if (sceneGraphClass == TableView.class) {
        final TableView<?> treeView = (TableView) sceneGraphObject;
        if (TableViewSampleData.canApplyTo(treeView)) {
          if (currentData instanceof TableViewSampleData) {
            newData = currentData;
          } else {
            newData = new TableViewSampleData();
          }
        } else {
          newData = null;
        }
      } else if (sceneGraphClass == TreeTableView.class) {
        final TreeTableView<?> treeTableView = (TreeTableView) sceneGraphObject;
        if (treeTableView.getRoot() == null) {
          if (currentData instanceof TreeTableViewSampleData) {
            newData = currentData;
          } else {
            newData = new TreeTableViewSampleData();
          }
        } else {
          newData = null;
        }
      } else if (sceneGraphClass == PieChart.class) {
        final PieChart pieChart = (PieChart) sceneGraphObject;
        if (pieChart.getData().isEmpty()) {
          if (currentData instanceof PieChartSampleData) {
            newData = currentData;
          } else {
            newData = new PieChartSampleData();
          }
        } else {
          newData = null;
        }
      } else if (XYChartSampleData.isKnownXYChart(sceneGraphObject)) {
        final XYChart<?, ?> xyChart = (XYChart) sceneGraphObject;
        if (xyChart.getData().isEmpty()) {
          if (currentData instanceof XYChartSampleData) {
            newData = currentData;
          } else {
            newData = new XYChartSampleData();
          }
        } else {
          newData = null;
        }
      } else {
        newData = null;
      }
    }

    if (newData == null) {
      if (currentData != null) {
        sampleDataMap.remove(startObject);
      }
    } else {
      newData.applyTo(sceneGraphObject);
      sampleDataMap.put(startObject, newData);
    }

    if (startObject instanceof FXOMInstance) {
      final FXOMInstance fxomInstance = (FXOMInstance) startObject;
      for (FXOMProperty p : fxomInstance.getProperties().values()) {
        if (p instanceof FXOMPropertyC) {
          final FXOMPropertyC pc = (FXOMPropertyC) p;
          for (FXOMObject v : pc.getValues()) {
            assignSampleData(v);
          }
        }
      }
    } else if (startObject instanceof FXOMCollection) {
      final FXOMCollection fxomCollection = (FXOMCollection) startObject;
      for (FXOMObject i : fxomCollection.getItems()) {
        assignSampleData(i);
      }
    }
  }
  protected void refreshWorklogTableViewAndResults() {

    // return early if no data present or still the same data
    // as the last time this tab was active
    Optional<FetchTimereportContext> reportContextOptional = this.fetchTimereportContext;
    if (!reportContextOptional.isPresent()
        || !reportContextOptional.get().getResult().isPresent()
        || !resultToDisplayChangedSinceLastRender) {
      LOGGER.debug(
          "[{}] No results to display or data not changed. Not refreshing TableView and data",
          getText());
      return;
    }

    SettingsUtil.Settings settings = SettingsUtil.loadSettings();
    if (settings.isShowStatistics() && statisticsView == null
        || !settings.isShowStatistics() && statisticsView != null) {
      // statistics are disabled and were previously rendered
      // or statistics are enabled and weren't rendered before
      // update content view
      LOGGER.debug("Updating contentView since settings for statistics seemed to have changed");
      setContent(getContentNode());
    }

    FetchTimereportContext timereportContext = reportContextOptional.get();
    TimerangeProvider timerangeProvider = timereportContext.getTimerangeProvider();

    // render the table columns if the timerange changed from last result
    if (!lastUsedTimerangeProvider.isPresent()
        || !lastUsedTimerangeProvider.get().equals(timerangeProvider)
        || (lastCollapseState.isPresent() && lastCollapseState.get() != settings.getCollapseState())
        || (lastHighlightState.isPresent()
            && lastHighlightState.get() != settings.getHighlightState())) {

      LOGGER.debug(
          "[{}] Regenerating columns for timerange {}",
          getText(),
          timerangeProvider.getReportTimerange().name());
      taskTableView.getColumns().clear();
      taskTableView.getColumns().add(taskStatusTreeTableColumn);
      taskTableView.getColumns().add(taskDescriptionTreeTableColumn);

      // render tables for all days in the selected timerange
      // e.g. timerange current month renders a column for
      // each day of the current month
      long amountOfDaysToDisplay =
          ChronoUnit.DAYS.between(timerangeProvider.getStartDate(), timerangeProvider.getEndDate());

      for (int days = 0; days <= amountOfDaysToDisplay; days++) {
        LocalDate currentColumnDate = timerangeProvider.getStartDate().plus(days, ChronoUnit.DAYS);
        String displayDate = FormattingUtil.formatDate(currentColumnDate);

        // worklog column
        taskTableView.getColumns().add(new WorklogTreeTableColumn(displayDate, currentColumnDate));
      }

      // also add another summary per task column
      taskTableView.getColumns().add(new TaskWorklogSummaryTreeTableColumn());

      lastUsedTimerangeProvider = Optional.of(timerangeProvider);
      lastCollapseState = Optional.of(settings.getCollapseState());
      lastHighlightState = Optional.of(settings.getHighlightState());
    }

    // refresh data
    LOGGER.debug("[{}] Refreshing items in TableView", getText());

    TreeItem<DisplayRow> root = taskTableView.getRoot();
    root.getChildren().clear();

    DisplayData displayData =
        getDisplayData(timereportContext, resultToDisplayChangedSinceLastRender);
    root.getChildren().addAll(displayData.getTreeRows());

    resultToDisplayChangedSinceLastRender = false;
  }