All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vaadin.flow.component.spreadsheet.SpreadsheetTable Maven / Gradle / Ivy

There is a newer version: 24.6.0
Show newest version
/**
 * Copyright 2000-2024 Vaadin Ltd.
 *
 * This program is available under Vaadin Commercial License and Service Terms.
 *
 * See {@literal } for the full
 * license.
 */
package com.vaadin.flow.component.spreadsheet;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFTable;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTAutoFilter;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTable;

/**
 * Represents a "table" inside a spreadsheet.
 *
 * A table is a region ( {@link CellRangeAddress}), that has {@link PopupButton}
 * on the column header cells of the region. In this context the column header
 * cells refer to the cells on the first row of the region.
 *
 * @author Vaadin Ltd.
 */
@SuppressWarnings("serial")
public class SpreadsheetTable implements Serializable {

    private final CellRangeAddress fullTableRegion;
    private final Sheet sheet;
    private final Spreadsheet spreadsheet;
    protected final Map popupButtons;
    private transient CTAutoFilter ctWorksheetAutoFilter;
    private transient XSSFTable xssfTable;

    /**
     * Creates a new table for the given spreadsheet component, its active sheet
     * (returned by {@link Spreadsheet#getActiveSheet()}) and the given region.
     * Adds pop-up buttons for table headers (cells in the first row).
     *
     * @param spreadsheet
     *            Target spreadsheet
     * @param tableRegion
     *            Cell range to build the table in
     */
    public SpreadsheetTable(Spreadsheet spreadsheet,
            CellRangeAddress tableRegion) {
        this(spreadsheet, spreadsheet.getActiveSheet(), tableRegion);
    }

    /**
     * Creates a new table for the given spreadsheet component, sheet and
     * region. If the component is currently displaying the sheet that the table
     * belongs to, pop-up buttons are added to table headers (first row cells).
     *
     * @param spreadsheet
     *            Target spreadsheet
     * @param sheet
     *            Target sheet within the spreadsheet
     * @param fullTableRegion
     *            Cell range to build the table in
     */
    public SpreadsheetTable(Spreadsheet spreadsheet, Sheet sheet,
            CellRangeAddress fullTableRegion) {
        this(spreadsheet, sheet, fullTableRegion, null, null);
    }

    /**
     * Creates a new table for the given spreadsheet component, sheet and region
     * while referencing the backing xssfTable or ctWorksheetAutoFilter. If the
     * component is currently displaying the sheet that the table belongs to,
     * pop-up buttons are added to table headers (first row cells).
     *
     * @param spreadsheet
     *            Target spreadsheet
     * @param sheet
     *            Target sheet within the spreadsheet
     * @param fullTableRegion
     *            Cell range to build the table in
     * @param ctWorksheetAutoFilter
     *            Set this to not-null if this table is backed by a
     *            XSSFSheet.getCTWorksheet().getAutoFilter()
     * @param xssfTable
     *            Set this to not-null if this table is backed by a XSSFTable
     */
    public SpreadsheetTable(Spreadsheet spreadsheet, Sheet sheet,
            CellRangeAddress fullTableRegion,
            CTAutoFilter ctWorksheetAutoFilter, XSSFTable xssfTable) {
        this.spreadsheet = spreadsheet;
        this.sheet = sheet;
        this.fullTableRegion = fullTableRegion;
        this.xssfTable = xssfTable;
        this.ctWorksheetAutoFilter = ctWorksheetAutoFilter;
        popupButtons = new HashMap();

        if (isTableSheetCurrentlyActive()) {
            initPopupButtons();
        }
    }

    /**
     * Reload the table's pop-up buttons, if spreadsheet component is currently
     * presenting the sheet this table belongs to.
     * 

* If there are no pop-up buttons stored, when {@link #clear()} has been * called, the pop-up buttons are recreated. Otherwise they are just added * to the spreadsheet component again. */ public void reload() { if (isTableSheetCurrentlyActive()) { if (popupButtons.isEmpty()) { initPopupButtons(); } else { for (PopupButton popupButton : popupButtons.values()) { spreadsheet.setPopup(popupButton.getCellReference(), popupButton); } } } } /** * Clears all the table's pop-up buttons and their pop-up content. */ public void clear() { for (PopupButton popupButton : popupButtons.values()) { popupButton.setContent(null); } popupButtons.clear(); } /** * Returns true if the spreadsheet component is currently displaying the * sheet that this table belongs to. * * @return true if the sheet this table belongs to is active */ public boolean isTableSheetCurrentlyActive() { return spreadsheet.getActiveSheet().equals(sheet); } /** * Initializes the pop-up buttons of this table. */ protected void initPopupButtons() { if (isActiveSheet(sheet)) { var targetCells = resolveCellsForPopupButtonCreation(); for (CellReference popupButtonTargetCell : targetCells) { PopupButton popupButton = new PopupButton(); popupButtons.put(popupButtonTargetCell, popupButton); spreadsheet.setPopup(popupButtonTargetCell, popupButton); } } } private List resolveCellsForPopupButtonCreation() { if (xssfTable != null) { // if this SpreadsheetTable is backed by XssfTable consider content // of its CTAutoFilter return resolveCellsForPopupButtonCreation(xssfTable.getCTTable()); } else { return getAllHeaderRowCells(); } } private List resolveCellsForPopupButtonCreation( CTTable table) { if (table.isSetAutoFilter()) { return getVisibleAutoFilterPopupButtonsCells(table); } else { // if AutoFilter is not set, then don't display any popup buttons return Collections.emptyList(); } } private List getVisibleAutoFilterPopupButtonsCells( CTTable table) { if (table.getAutoFilter().getFilterColumnList().isEmpty()) { // if there are no filter columns in this list, then display // filter popup buttons for all columns (strange, I know) return getAllHeaderRowCells(); } else { // otherwise display filter popup buttons only for columns where the // popup buttons are not hidden return table.getAutoFilter().getFilterColumnList().stream() .filter(filterColumn -> !filterColumn.isSetHiddenButton()) .map(filterColumn -> new CellReference(sheet.getSheetName(), fullTableRegion.getFirstRow(), (int) filterColumn.getColId(), true, true)) .collect(Collectors.toList()); } } private List getAllHeaderRowCells() { var result = new ArrayList(); for (int c = fullTableRegion.getFirstColumn(); c <= fullTableRegion .getLastColumn(); c++) { CellReference popupButtonCellReference = new CellReference( sheet.getSheetName(), fullTableRegion.getFirstRow(), c, true, true); result.add(popupButtonCellReference); } return result; } private boolean isActiveSheet(Sheet sheet) { return sheet.equals(spreadsheet.getActiveSheet()); } /** * Gets the {@link Sheet} this table belongs to. * * @return Sheet this table belongs to */ public Sheet getSheet() { return sheet; } /** * Gets the {@link Spreadsheet} component this table belongs to. * * @return Spreadsheet this table belongs to */ public Spreadsheet getSpreadsheet() { return spreadsheet; } /** * Gets the full table region, {@link CellRangeAddress} for this table. * * @return Table region */ public CellRangeAddress getFullTableRegion() { return fullTableRegion; } /** * Gets the {@link PopupButton} for the given column. If given column is * outside of the table region, null will be returned. * * @param col * Column index, 0-based * @return the {@link PopupButton} contained in the header column of this * table. */ public PopupButton getPopupButton(int col) { for (PopupButton button : popupButtons.values()) { if (button.getColumn() == col) { return button; } } return null; } /** * Gets the {@link PopupButton} for the header cell pointed by * {@link CellReference}. If given reference is not a header cell for this * table, or is outside of the table region, null will be * returned. * * @param filterCellReference * header cell reference * @return Pop-up button from the given cell, or null if not found */ public PopupButton getPopupButton(CellReference filterCellReference) { return popupButtons.get(filterCellReference); } /** * Returns all of the {@link PopupButton}s for this table. * * @return the pop-up buttons for this table in no specific order. */ public Collection getPopupButtons() { return Collections.unmodifiableCollection(popupButtons.values()); } /** * Sets the CTAutoFilter object that represents this table in the underlying * POI model. * * @param ctWorksheetAutoFilter * Referenced autofilter. */ protected void setCtWorksheetAutoFilter( CTAutoFilter ctWorksheetAutoFilter) { this.ctWorksheetAutoFilter = ctWorksheetAutoFilter; } /** * @return Returns the CTAutoFilter object that represents this table in the * underlying POI model. Can be null if this table is not backed by * a Worksheet CTAutoFilter. */ public CTAutoFilter getCtWorksheetAutoFilter() { return ctWorksheetAutoFilter; } /** * Sets the XSSFTable object that represents this table in the underlying * POI model. * * @param xssfTable * Referenced table. */ protected void setXssfTable(XSSFTable xssfTable) { this.xssfTable = xssfTable; } /** * @return Returns the XSSFTable object that represents this table in the * underlying POI model. Can be null if this table is not backed by * a XSSFTable. */ public XSSFTable getXssfTable() { return xssfTable; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy