Printable colum visible=false

Hello,

I want to print a table column (from Excel Button) but I don’t want to be visible in my Browser Table.

 transactionsTable.addPrintable("payAmount", new Table.Printable<Transaction, BigDecimal>() {
  @Nonnull
            @Override
            public BigDecimal getValue(Transaction item) {             
                    return item.getPayments().get(0).getPayAmount();              
        });
    }

Setting visible = false means that the column will not be present (visible) in excel table.
Is it possible?

Best Regards,
-n

Hello, @neutrino

This is possible if you create a new action that extends from Excel Action (How to create custom action) and use the collapsed attribute of the Column instead of the visible attribute.

  1. Create an action class and add the @ActionType annotation with the desired type name:
package com.company.sample.web.actions;

import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.gui.ComponentsHelper;
import com.haulmont.cuba.gui.Notifications;
import com.haulmont.cuba.gui.actions.list.ExcelAction;
import com.haulmont.cuba.gui.components.ActionType;
import com.haulmont.cuba.gui.components.DataGrid;
import com.haulmont.cuba.gui.components.Table;
import com.haulmont.cuba.gui.components.Window;
import com.haulmont.cuba.gui.export.ExcelExporter;
import com.haulmont.cuba.gui.export.ExportDisplay;

import java.util.ArrayList;

@ActionType("customExcel")
public class CustomExcelAction extends ExcelAction {

    @Override
    protected void export(ExcelExporter.ExportMode exportMode) {
        ExcelExporter exporter = new ExcelExporter();
        exporter.setExportAggregation(exportAggregation);

        Window window = ComponentsHelper.getWindowNN(target);

        ExportDisplay display = beanLocator.get(ExportDisplay.NAME);
        display.setFrame(window);

        if (target instanceof Table) {
            @SuppressWarnings("unchecked")
            Table<Entity> table = (Table<Entity>) target;
            // print all Table columns
            exporter.exportTable(table, new ArrayList<>(table.getColumns()), false, display, null, fileName, exportMode);
        }

        if (target instanceof DataGrid) {
            @SuppressWarnings("unchecked")
            DataGrid<Entity> dataGrid = (DataGrid<Entity>) target;
            // print all DataGrid columns
            exporter.exportDataGrid(dataGrid, new ArrayList<>(dataGrid.getColumns()), display, null, fileName, exportMode);
        }

        if (exporter.isXlsMaxRowNumberExceeded()) {
            Notifications notifications = ComponentsHelper.getScreenContext(target).getNotifications();

            notifications.create(Notifications.NotificationType.WARNING)
                    .withCaption(messages.getMainMessage("actions.warningExport.title"))
                    .withDescription(messages.getMainMessage("actions.warningExport.message"))
                    .show();
        }
    }
}
  1. In the web-spring.xml file, add <gui:actions> element with the base-packages attribute pointing to a package where to find your annotated actions:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:gui="http://schemas.haulmont.com/cuba/spring/cuba-gui.xsd">

    <!-- Annotation-based beans -->
    <context:component-scan base-package="com.company.sample"/>
    
    <gui:screens base-packages="com.company.sample.web"/>

    <gui:actions base-packages="com.company.sample.web.actions"/>

</beans>
  1. Now you can use the action in screen descriptors by specifying its type:
<groupTable id="personsTable"
            width="100%"
            dataContainer="personsDc">
    <actions>
        <action id="create" type="create"/>
        <action id="edit" type="edit"/>
        <action id="remove" type="remove"/>
        <action id="excel" type="customExcel"/>
    </actions>
    <columns>
        <column id="name" collapsed="true"/>
        <column id="lastName"/>
        <column id="age"/>
    </columns>
    <rowsCount/>
    <buttonsPanel id="buttonsPanel"
                  alwaysVisible="true">
        <button id="createBtn" action="personsTable.create"/>
        <button id="editBtn" action="personsTable.edit"/>
        <button id="removeBtn" action="personsTable.remove"/>
        <button id="excelBtn" action="personsTable.excel"/>
    </buttonsPanel>
</groupTable>

Result

  1. Browser - The Name column is not displayed.
  2. Excel - The Name column is displayed.
    image

Regards,
Gleb

Hi Gleb,

Very nice solution, indeed.
The problem is the column is not in the container (is not a property), I added it manually in order to print it (is about many to many relation).
In conclusion when I try to add collapsed attribute to column I have: IllegalArgumentException: Property 'myCol' was not found in the container.

Best Regards,
-n

I created an action new package in mycomp.web, made a new class CustomExcelAction

but when I try to open Transaction Browse Table I have

 Unable to get constructor for 'class mycomp.web.actions.CustomExcelAction' action
NoSuchMethodException:mycomp.web.actions.CustomExcelAction.<init>(java.lang.String)

Hello @neutrino!

Sorry, I forgot to override the constructor call.

@ActionType(CustomExcelAction.ID)
public class CustomExcelAction extends ExcelAction {

    public static final String ID = "customExcel";

    public CustomExcelAction() {
        this(ID);
    }

    public CustomExcelAction(String id) {
        super(id);
    }

    @Override
    protected void export(ExcelExporter.ExportMode exportMode) {
        ExcelExporter exporter = new ExcelExporter();
        exporter.setExportAggregation(exportAggregation);

        Window window = ComponentsHelper.getWindowNN(target);

        ExportDisplay display = beanLocator.get(ExportDisplay.NAME);
        display.setFrame(window);

        if (target instanceof Table) {
            @SuppressWarnings("unchecked")
            Table<Entity> table = (Table<Entity>) target;
            // print all Table columns
            exporter.exportTable(table, new ArrayList<>(table.getColumns()), false, display, null, fileName, exportMode);
        }

        if (target instanceof DataGrid) {
            @SuppressWarnings("unchecked")
            DataGrid<Entity> dataGrid = (DataGrid<Entity>) target;
            // print all DataGrid columns
            exporter.exportDataGrid(dataGrid, new ArrayList<>(dataGrid.getColumns()), display, null, fileName, exportMode);
        }

        if (exporter.isXlsMaxRowNumberExceeded()) {
            Notifications notifications = ComponentsHelper.getScreenContext(target).getNotifications();

            notifications.create(Notifications.NotificationType.WARNING)
                    .withCaption(messages.getMainMessage("actions.warningExport.title"))
                    .withDescription(messages.getMainMessage("actions.warningExport.message"))
                    .show();
        }
    }
}

If you want to use the generated column when exporting to an XLS file than you should use the Table#PrintableColumnGenerator interface (link to the documentation). The value for a cell in an XLS document is defined in the getValue() method of this interface.

Screen Controller

@UiController("sample_Person.browse")
@UiDescriptor("person-browse.xml")
@LookupComponent("personsTable")
@LoadDataBeforeShow
public class PersonBrowse extends StandardLookup<Person> {

    @Inject
    protected GroupTable<Person> personsTable;
    @Inject
    protected UiComponents uiComponents;

    @Subscribe
    protected void onBeforeShow(BeforeShowEvent event) {
        personsTable.addGeneratedColumn("customColumn", new Table.PrintableColumnGenerator<Person, String>() {
            @Override
            public String getValue(Person person) {
                return person.getName() + " : " + person.getLastName();
            }

            @Nullable
            @Override
            public Component generateCell(Person person) {
                Label<String> label = uiComponents.create(Label.NAME);
                label.setValue(person.getName() + " : " + person.getLastName());
                return label;
            }
        });

        Table.Column<Person> customColumn = personsTable.getColumn("customColumn");
        customColumn.setCollapsed(true);
        customColumn.setCaption("Custom Column");
    }
}

XML descriptor

<groupTable id="personsTable"
            width="100%"
            dataContainer="personsDc">
    <actions>
        <action id="create" type="create"/>
        <action id="edit" type="edit"/>
        <action id="remove" type="remove"/>
        <action id="excel" type="customExcel"/>
    </actions>
    <columns>
        <column id="name"/>
        <column id="lastName"/>
        <column id="age"/>
    </columns>
    <rowsCount/>
    <buttonsPanel id="buttonsPanel"
                  alwaysVisible="true">
        <button id="createBtn" action="personsTable.create"/>
        <button id="editBtn" action="personsTable.edit"/>
        <button id="removeBtn" action="personsTable.remove"/>
        <button id="excelBtn" action="personsTable.excel"/>
    </buttonsPanel>
</groupTable>

web-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:gui="http://schemas.haulmont.com/cuba/spring/cuba-gui.xsd">

    <!-- Annotation-based beans -->
    <context:component-scan base-package="com.company.sample"/>
    
    <gui:screens base-packages="com.company.sample.web"/>

    <gui:actions base-packages="com.company.sample.web.actions"/>

</beans>

Result

Browser - The customColumn is not displayed


Excel - The customColumn is displayed
image

Regards,
Gleb

Very good solution.
Actually I used only personsTable.addPrintable(.......);

Thank you,
-n

In order to see collapsed="true" must perform Help/Settings/Reset Settings of screen.Pay attention: all screens should be closed before to do that.