hr.restart.swing.raExtendedTable.java Source code

Java tutorial

Introduction

Here is the source code for hr.restart.swing.raExtendedTable.java

Source

/****license*****************************************************************
**   file: raExtendedTable.java
**   Copyright 2006 Rest Art
**
**   Licensed under the Apache License, Version 2.0 (the "License");
**   you may not use this file except in compliance with the License.
**   You may obtain a copy of the License at
**
**       http://www.apache.org/licenses/LICENSE-2.0
**
**   Unless required by applicable law or agreed to in writing, software
**   distributed under the License is distributed on an "AS IS" BASIS,
**   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
**   See the License for the specific language governing permissions and
**   limitations under the License.
**
****************************************************************************/
package hr.restart.swing;

import hr.restart.robno.repMemo;
import hr.restart.sisfun.frmParam;
import hr.restart.util.Aus;
import hr.restart.util.Util;
import hr.restart.util.Valid;
import hr.restart.util.VarStr;
import hr.restart.util.raJPTableView;
import hr.restart.util.reports.repDynamicProvider;

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;

import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.hssf.util.Region;

import com.borland.dx.dataset.DataSet;
import com.borland.dx.dataset.SortDescriptor;

/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2002</p>
 * <p>Company: Rest-Art</p>
 * @author ab.f
 * @version 1.0
 */

public class raExtendedTable extends JraTable2 {
    JPopupMenu pop = new JPopupMenu();
    JMenuItem jmiNewGroup = new JMenuItem("Dodaj grupiranje po koloni");
    JMenuItem jmiAddGroup = new JMenuItem("Ubaci kolonu u grupu");
    JMenuItem jmiRemGroup = new JMenuItem("Izbaci kolonu iz grupe");
    JMenuItem jmiAddSort = new JMenuItem("Ubaci kolonu u poredak");
    JMenuItem jmiRemove = new JMenuItem("Izbaci kolonu iz poretka");
    JMenuItem jmiAddSum = new JMenuItem("Zbroji kolonu");
    JMenuItem jmiRemSum = new JMenuItem("Poniti zbrajanje kolone");
    JMenuItem jmiRemoveAll = new JMenuItem("Poniti grupiranje i poredak");

    String clickCol;
    ArrayList group, sort;
    String lastAddedSort;
    boolean forcePage;

    raJPTableView owner;

    public raExtendedTable() {
        super();
        createHeaderMouseListener();
        createPopup();
        group = new ArrayList();
        sort = new ArrayList();
        getTableHeader().setDefaultRenderer(new HeaderRenderer());
    }

    public void setOwner(raJPTableView owner) {
        this.owner = owner;
    }

    public raJPTableView getOwner() {
        return owner;
    }

    String oldcolname = "";

    private void createHeaderMouseListener() {
        getTableHeader().removeMouseListener(tableHeaderMouseListener);
        tableHeaderMouseListener = new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                if (!isEnabled() || getDataSet() == null)
                    return;
                if (e.isPopupTrigger())
                    showPopup(e);
                else if ((e.getModifiers() & e.BUTTON1_MASK) == e.BUTTON1_MASK)
                    leftClick(e);
            }

            public void mousePressed(MouseEvent e) {
                if (!isEnabled() || getDataSet() == null)
                    return;
                if (e.isPopupTrigger())
                    showPopup(e);
            }

            public void mouseReleased(MouseEvent e) {
                if (!isEnabled() || getDataSet() == null)
                    return;
                if (e.isPopupTrigger())
                    showPopup(e);
            }
        };
    }

    private void createPopup() {
        pop = new JPopupMenu();
        pop.add(jmiAddSort);
        pop.add(jmiRemove);
        pop.addSeparator();
        pop.add(jmiNewGroup);
        pop.add(jmiAddGroup);
        pop.add(jmiRemGroup);
        pop.addSeparator();
        pop.add(jmiAddSum);
        pop.add(jmiRemSum);
        pop.addSeparator();
        pop.add(jmiRemoveAll);
        jmiNewGroup.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (clickCol.equalsIgnoreCase(lastAddedSort))
                    lastAddedSort = null;
                sort.remove(ColumnInfo.get(clickCol));
                addToGroup(clickCol, true, true);
                createSortDescriptor();
            }
        });
        jmiAddGroup.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (clickCol.equalsIgnoreCase(lastAddedSort))
                    lastAddedSort = null;
                sort.remove(ColumnInfo.get(clickCol));
                addToGroup(clickCol, true, false);
                createSortDescriptor();
            }
        });
        jmiAddSort.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (lastAddedSort != null && sort.contains(ColumnInfo.get(lastAddedSort)))
                    lastAddedSort = clickCol;
                sort.add(new ColumnInfo(clickCol));
                createSortDescriptor();
            }
        });
        jmiRemGroup.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                group.remove(ColumnInfo.get(clickCol));
                renumberGroups();
                createSortDescriptor();
            }
        });
        jmiRemove.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                sort.remove(ColumnInfo.get(clickCol));
                createSortDescriptor();
            }
        });
        jmiRemoveAll.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                group.clear();
                sort.clear();
                createSortDescriptor();
            }
        });
        jmiAddSum.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                owner.getStorageDataSet().last();
                owner.toggleKumul(clickCol);
                owner.destroy_kum();
                owner.setKumTak(owner.getStoZbrojiti() != null);
                owner.init_kum();
            }
        });
        jmiRemSum.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                owner.toggleKumul(clickCol);
                owner.destroy_kum();
                owner.setKumTak(owner.getStoZbrojiti() != null);
                owner.init_kum();
            }
        });
    }

    private void showPopup(MouseEvent e) {
        if (getDataSet() == null)
            return;
        int idx = getTableHeader().columnAtPoint(e.getPoint());
        clickCol = getRealColumnName(idx);
        ColumnInfo ci = ColumnInfo.get(clickCol);
        jmiNewGroup.setEnabled(!group.contains(ci));
        jmiAddGroup.setEnabled(!group.contains(ci) && group.size() > 0);
        jmiRemGroup.setEnabled(group.contains(ci));
        jmiAddSort.setEnabled(!group.contains(ci) && !sort.contains(ci));
        jmiRemove.setEnabled(sort.contains(ci));
        jmiRemoveAll.setEnabled(group.size() + sort.size() > 0);
        if (Valid.getValid().isNumeric(getDataSet().getColumn(clickCol))) {
            boolean sum = (owner.getStoZbrojiti() != null
                    && Util.getUtil().containsArr(owner.getStoZbrojiti(), clickCol));
            jmiAddSum.setEnabled(!sum);
            jmiRemSum.setEnabled(sum);
        } else {
            jmiAddSum.setEnabled(false);
            jmiRemSum.setEnabled(false);
        }
        getColumnModel().getSelectionModel().setSelectionInterval(idx, idx);
        pop.show((Component) e.getSource(), e.getX(), e.getY());
    }

    private void leftClick(MouseEvent e) {
        if (getDataSet() == null)
            return;
        // Hrvatski Locale
        /*if (getDataSet() instanceof StorageDataSet) {
          StorageDataSet sds = (StorageDataSet) getDataSet();
          if (sds.getLocale() == null) sds.setLocale(Locale.getDefault());
        }*/
        int idx = getTableHeader().columnAtPoint(e.getPoint());
        clickCol = getRealColumnName(getTableHeader().columnAtPoint(e.getPoint()));
        ColumnInfo ci = ColumnInfo.get(clickCol);
        if (group.contains(ci))
            ((ColumnInfo) group.get(group.indexOf(ci))).toggle();
        else if (sort.contains(ci))
            ((ColumnInfo) sort.get(sort.indexOf(ci))).toggle();
        else {
            if (lastAddedSort != null && sort.contains(ColumnInfo.get(lastAddedSort)))
                sort.remove(ColumnInfo.get(lastAddedSort));
            if (lastAddedSort == null)
                sort.clear();
            sort.add(new ColumnInfo(lastAddedSort = clickCol));
        }
        getColumnModel().getSelectionModel().setSelectionInterval(idx, idx);
        createSortDescriptor();
        String newcolname = getColumnModel().getColumn(getTableHeader().columnAtPoint(e.getPoint()))
                .getHeaderValue().toString();

        //raExtendedTable.this.firePropertyChange(COLNAMEPROPERTY,oldcolname,newcolname);
        fireColumnChanged(oldcolname, newcolname);
        oldcolname = newcolname;
        setSpeedColumn(getTableHeader().columnAtPoint(e.getPoint()));
    }

    private void generateSort(DataSet ds) {
        group.clear();
        sort.clear();
        if (ds != null && ds.getSort() != null) {
            SortDescriptor sd = ds.getSort();
            for (int i = 0; i < sd.getKeys().length; i++)
                addSort(sd.getKeys()[i], sd.getDescending() == null ? true : !sd.getDescending()[i]);
        }
    }

    public void setDataSet(DataSet ds) {
        generateSort(ds);
        super.setDataSet(ds);
    }

    public void createSortDescriptor() {
        if (group.size() + sort.size() == 0) {
            raSelectTableModifier stm = hasSelectionTrackerInstalled();
            if (stm != null && stm.isNatural())
                stm.clearSelection();
            getDataSet().setSort(original);
            if (isShowing())
                getTableHeader().repaint();
            return;
        }
        String[] names = new String[countGroups() + sort.size()];
        boolean[] asc = new boolean[countGroups() + sort.size()];
        int ng = 0;
        for (int i = 0; i < group.size(); i++)
            if (i == 0 || ((ColumnInfo) group.get(i - 1)).numgroup != ((ColumnInfo) group.get(i)).numgroup) {
                names[ng] = ((ColumnInfo) group.get(i)).colname;
                asc[ng++] = !((ColumnInfo) group.get(i)).ascending;
            }
        for (int i = 0; i < sort.size(); i++) {
            names[i + ng] = ((ColumnInfo) sort.get(i)).colname;
            asc[i + ng] = !((ColumnInfo) sort.get(i)).ascending;
        }
        SortDescriptor sd = new SortDescriptor("", names, asc, true, false, null);
        if (isShowing())
            getTableHeader().repaint();
        raSelectTableModifier stm = hasSelectionTrackerInstalled();
        if (stm != null && stm.isNatural())
            stm.clearSelection();
        getDataSet().setSort(sd);
    }

    public void addToGroup(String name, boolean asc, String[] descs, String get, boolean newGroup) {
        ColumnInfo ci = new ColumnInfo(name, countGroups() + (newGroup ? 1 : 0));
        ci.ascending = asc;
        ci.descs = descs;
        ci.get = get;
        group.add(ci);
    }

    public void addToGroup(String name, boolean asc, String[] descs, DataSet getDs, boolean newGroup) {
        ColumnInfo ci = new ColumnInfo(name, countGroups() + (newGroup ? 1 : 0));
        ci.ascending = asc;
        ci.descs = descs;
        ci.getDs = getDs;
        group.add(ci);
    }

    public void addToGroup(String name, boolean asc, boolean newGroup) {
        addToGroup(name, asc, null, (String) null, newGroup);
    }

    public void addSort(String name, boolean asc) {
        ColumnInfo ci = new ColumnInfo(name);
        ci.ascending = asc;
        sort.add(ci);
        lastAddedSort = name;
    }

    SortDescriptor original = null;

    public void resetSortColumns() {
        group.clear();
        sort.clear();
        if (getDataSet() != null) {
            original = getDataSet().getSort();
            generateSort(getDataSet());
        } else
            original = null;
        lastAddedSort = null;
        if (isShowing())
            getTableHeader().repaint();
    }

    public boolean isCustomSort() {
        return (group.size() + sort.size() > 0);
    }

    public boolean inGroup(String name) {
        return group.contains(ColumnInfo.get(name));
    }

    private void renumberGroups() {
        for (int i = 0, gr = 0, old = 0; i < group.size(); i++) {
            ColumnInfo ci = (ColumnInfo) group.get(i);
            if (i == 0 || ci.numgroup != old) {
                old = ci.numgroup;
                ++gr;
            }
            ci.numgroup = gr;
        }
    }

    public void dumpAll() {
        for (int i = 0; i < group.size(); i++)
            ((ColumnInfo) group.get(i)).dump();
        for (int i = 0; i < sort.size(); i++)
            ((ColumnInfo) sort.get(i)).dump();
    }

    private int countGroups() {
        return group.size() == 0 ? 0 : ((ColumnInfo) group.get(group.size() - 1)).numgroup;
    }

    public int getTotalGroupCount() {
        return group.size();
    }

    public int getGroupCount() {
        return countGroups();
    }

    public String getGroup(int n) {
        return ((ColumnInfo) group.get(n)).colname;
    }

    public String getRealGroup(int n) {
        for (int i = 0; i < group.size(); i++)
            if (((ColumnInfo) group.get(i)).numgroup == n)
                return ((ColumnInfo) group.get(i)).colname;
        return "";
    }

    public boolean isRealGroup(int n) {
        return (n == 0 || ((ColumnInfo) group.get(n)).numgroup != ((ColumnInfo) group.get(n - 1)).numgroup);
    }

    public boolean isGroupDescending(int n) {
        return !((ColumnInfo) group.get(n)).ascending;
    }

    public int getGroupNum(int n) {
        return ((ColumnInfo) group.get(n)).numgroup;
    }

    public String[] getGroupDesc(int n) {
        return ((ColumnInfo) group.get(n)).descs;
    }

    public String getGroupGet(int n) {
        return ((ColumnInfo) group.get(n)).get;
    }

    public DataSet getGroupGetDs(int n) {
        return ((ColumnInfo) group.get(n)).getDs;
    }

    public boolean isForcePage() {
        return forcePage;
    }

    public void setForcePage(boolean forcePage) {
        this.forcePage = forcePage;
    }

    private String xlsRange(int firstRow, int lastRow, short column) {
        char cc = (char) ('A' + column);
        return "" + cc + firstRow + ":" + cc + lastRow;
    }

    public void exportToXLS(File output) {
        String fname = output.getName();
        if (!fname.endsWith("xls") && fname.indexOf('.') < 0)
            output = new File(output.getParentFile(), fname + ".xls");
        System.out.println("exporting to XLS");
        HSSFWorkbook wb = new HSSFWorkbook();

        HSSFDataFormat df = wb.createDataFormat();

        String fontFamily = frmParam.getParam("sisfun", "excelFont", "Arial", "Font za export u Excel", true);
        if (fontFamily == null || fontFamily.length() == 0)
            fontFamily = "Arial";

        int fontSize = 10;
        String fontSizeTx = frmParam.getParam("sisfun", "excelFontSize", "10",
                "Veliina fonta za export u Excel, u tokama", true);
        if (fontSizeTx != null && Aus.getNumber(fontSizeTx) >= 6 && Aus.getNumber(fontSizeTx) <= 72)
            fontSize = Aus.getNumber(fontSizeTx);

        HSSFFont font = wb.createFont();
        font.setFontName(fontFamily);
        font.setFontHeightInPoints((short) fontSize);

        HSSFFont fontTitle = wb.createFont();
        fontTitle.setFontName(fontFamily);
        fontTitle.setFontHeightInPoints((short) (fontSize * 1.8));

        HSSFFont fontSubtitle = wb.createFont();
        fontSubtitle.setFontName(fontFamily);
        fontSubtitle.setFontHeightInPoints((short) (fontSize * 1.5));

        HSSFCellStyle csHeader = wb.createCellStyle();
        csHeader.setFont(font);
        csHeader.setFillBackgroundColor(HSSFColor.GREY_25_PERCENT.index);
        csHeader.setFillForegroundColor(HSSFColor.GREY_25_PERCENT.index);
        csHeader.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        csHeader.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        csHeader.setDataFormat(df.getFormat("text"));

        HSSFCellStyle csFooter = wb.createCellStyle();
        csFooter.setFont(font);
        csFooter.setFillBackgroundColor(HSSFColor.GREY_25_PERCENT.index);
        csFooter.setFillForegroundColor(HSSFColor.GREY_25_PERCENT.index);
        csFooter.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        csFooter.setAlignment(HSSFCellStyle.ALIGN_LEFT);
        csFooter.setDataFormat(df.getFormat("text"));

        HSSFCellStyle csFooterNum2 = wb.createCellStyle();
        csFooterNum2.setFont(font);
        csFooterNum2.setFillBackgroundColor(HSSFColor.GREY_25_PERCENT.index);
        csFooterNum2.setFillForegroundColor(HSSFColor.GREY_25_PERCENT.index);
        csFooterNum2.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        csFooterNum2.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
        csFooterNum2.setDataFormat(df.getFormat("#,##0.00"));

        HSSFCellStyle csFooterNum = wb.createCellStyle();
        csFooterNum.setFont(font);
        csFooterNum.setFillBackgroundColor(HSSFColor.GREY_25_PERCENT.index);
        csFooterNum.setFillForegroundColor(HSSFColor.GREY_25_PERCENT.index);
        csFooterNum.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        csFooterNum.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
        csFooterNum.setDataFormat(df.getFormat("#"));

        HSSFCellStyle csDate = wb.createCellStyle();
        csDate.setFont(font);
        csDate.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        csDate.setDataFormat(df.getFormat("dd.mm.yyyy"));

        HSSFCellStyle csTitle = wb.createCellStyle();
        csTitle.setFont(fontTitle);
        csTitle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        csTitle.setDataFormat(df.getFormat("text"));

        HSSFCellStyle csSubtitle = wb.createCellStyle();
        csSubtitle.setFont(fontSubtitle);
        csSubtitle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        csSubtitle.setDataFormat(df.getFormat("text"));

        HSSFCellStyle csNum2 = wb.createCellStyle();
        csNum2.setFont(font);
        csNum2.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
        csNum2.setDataFormat(df.getFormat("#,##0.00"));

        HSSFCellStyle csNum3 = wb.createCellStyle();
        csNum3.setFont(font);
        csNum3.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
        csNum3.setDataFormat(df.getFormat("#,##0.000"));

        HSSFCellStyle csNum = wb.createCellStyle();
        csNum.setFont(font);
        csNum.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
        csNum.setDataFormat(df.getFormat("#.#"));

        HSSFCellStyle csInt = wb.createCellStyle();
        csInt.setFont(font);
        csInt.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
        csInt.setDataFormat(df.getFormat("#"));

        HSSFCellStyle csText = wb.createCellStyle();
        csText.setFont(font);
        csText.setAlignment(HSSFCellStyle.ALIGN_LEFT);
        csText.setDataFormat(df.getFormat("text"));

        repDynamicProvider dp = repDynamicProvider.getInstance();
        boolean sums = dp.hasSumRow();
        int cols = getColumnModel().getColumnCount();
        int rows = getRowCount() - (sums ? 1 : 0);

        HSSFSheet sheet = wb.createSheet();
        HSSFRow row;
        HSSFCell cell;

        short cRow = 0;

        // header and title
        row = sheet.createRow(cRow = 0);
        cell = row.createCell((short) 0);
        cell.setCellStyle(csText);
        if (cols > 1)
            sheet.addMergedRegion(new Region(cRow, (short) 0, cRow, (short) (cols - 1)));
        cell.setEncoding(wb.ENCODING_UTF_16);
        cell.setCellValue(repMemo.getrepMemo().getOneLine());

        row = sheet.createRow(++cRow);
        cell = row.createCell((short) 0);
        cell.setCellStyle(csTitle);
        if (cols > 1)
            sheet.addMergedRegion(new Region(cRow, (short) 0, cRow, (short) (cols - 1)));
        cell.setEncoding(wb.ENCODING_UTF_16);
        if (dp.getTitle().length() > 0)
            cell.setCellValue(dp.getTitle().substring(1));
        else
            cell.setCellValue("");

        if (dp.getSubtitle().length() > 0) {
            row = sheet.createRow(++cRow);
            cell = row.createCell((short) 0);
            cell.setCellStyle(csSubtitle);
            if (cols > 1)
                sheet.addMergedRegion(new Region(cRow, (short) 0, cRow, (short) (cols - 1)));
            cell.setEncoding(wb.ENCODING_UTF_16);
            cell.setCellValue(dp.getSubtitle().substring(1));
        }

        for (short c = 0; c < cols; c++)
            sheet.setColumnWidth(c, (short) (getColumnModel().getColumn(c).getWidth() * 40));

        // sections
        row = sheet.createRow(++cRow);
        int secRow = 0, firstRow = 0;

        for (int r = 0; r < rows; r++) {
            if (r == 0) {
                row = sheet.createRow(++cRow);
                for (short c = 0; c < cols; c++) {
                    cell = row.createCell(c);
                    cell.setCellStyle(csHeader);
                    cell.setEncoding(wb.ENCODING_UTF_16);
                    cell.setCellValue(getColumnModel().getColumn(c).getHeaderValue().toString());
                }
                if (firstRow == 0)
                    firstRow = cRow;
                secRow = cRow;
            }
            row = sheet.createRow(++cRow);
            for (short c = 0; c < cols; c++) {
                cell = row.createCell(c);
                Object o = getValueAt(r, c);
                if (o instanceof Number) {
                    if (o instanceof BigDecimal) {
                        BigDecimal bd = (BigDecimal) o;
                        if (bd.scale() == 2)
                            cell.setCellStyle(csNum2);
                        else if (bd.scale() == 3)
                            cell.setCellStyle(csNum3);
                        else
                            cell.setCellStyle(csNum);
                        cell.setCellValue(bd.doubleValue());
                    } else {
                        String t = dp.getValueAt(r, c);
                        if (Aus.isDigit(t)) {
                            cell.setCellStyle(csInt);
                            cell.setCellValue(((Number) o).doubleValue());
                        } else {
                            cell.setCellStyle(csText);
                            cell.setEncoding(wb.ENCODING_UTF_16);
                            cell.setCellValue(t);
                        }
                    }
                } else if (o instanceof Date) {
                    cell.setCellStyle(csDate);
                    cell.setCellValue((Date) o);
                } else {
                    cell.setCellStyle(csText);
                    cell.setEncoding(wb.ENCODING_UTF_16);
                    cell.setCellValue(dp.getValueAt(r, c));
                }
            }
        }
        System.out.println("sums " + sums);
        if (sums) {
            int non = 0;
            while (non < cols && dp.getValueAt(getRowCount() - 1, non).trim().length() == 0)
                ++non;
            if (non < cols) {
                System.out.println("creating row " + non);
                row = sheet.createRow(++cRow);

                if (non > 0) {
                    cell = row.createCell((short) 0);
                    cell.setCellStyle(csFooter);
                    cell.setEncoding(wb.ENCODING_UTF_16);
                    cell.setCellValue("U K U P N O");
                    if (non > 1)
                        sheet.addMergedRegion(new Region(cRow, (short) 0, cRow, (short) (non - 1)));
                }
                for (short c = (short) non; c < cols; c++) {
                    cell = row.createCell(c);
                    Object o = getValueAt(rows - 1, c);
                    if ((o instanceof BigDecimal) && ((BigDecimal) o).scale() == 2)
                        cell.setCellStyle(csFooterNum2);
                    else
                        cell.setCellStyle(csFooterNum);
                    if (dp.getValueAt(getRowCount() - 1, c).trim().length() != 0)
                        cell.setCellFormula("SUBTOTAL(9;" + xlsRange(firstRow + 1, cRow, c) + ")");
                    else
                        cell.setCellValue("");
                }
            }
        }
        FileOutputStream out = null;

        try {
            out = new FileOutputStream(output);
            wb.write(out);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null)
                try {
                    out.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
        }
    }

    class HeaderRenderer extends DefaultTableCellRenderer {
        int num;
        Font ital, norm;

        //    Font tiny;
        public HeaderRenderer() {
            super();
            setHorizontalAlignment(JLabel.CENTER);
        }

        public Component getTableCellRendererComponent(JTable t, Object v, boolean sel, boolean foc, int row,
                int col) {
            num = -1;
            setFont(norm != null ? norm : (norm = getFont()));
            if (t != null) {
                JTableHeader header = t.getTableHeader();
                if (header != null) {
                    setForeground(header.getForeground());
                    setBackground(header.getBackground());
                    setFont(header.getFont());
                    if (getDataSet() != null) {
                        String cn = getRealColumnName(col);
                        if (group.contains(ColumnInfo.get(cn)))
                            setFont(ital != null ? ital : (ital = norm.deriveFont(Font.ITALIC | Font.BOLD)));
                        else
                            num = sort.indexOf(ColumnInfo.get(cn));
                    }
                }
            }
            setText((v == null) ? "" : v.toString());
            setBorder(UIManager.getBorder("TableHeader.cellBorder"));
            try {
                if (getPreferredSize().width > t.getCellRect(row, col, false).width)
                    setToolTipText(getText());
                else
                    setToolTipText(null);
            } catch (Exception e) {
                setToolTipText(null);
            }
            return this;
        }

        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (num >= 0) {
                Color sh1 = getBackground().darker();
                Color sh2 = sh1.darker();
                Color hi1 = getBackground().brighter();
                Color hi2 = hi1.brighter();
                ColumnInfo ci = (ColumnInfo) sort.get(num);
                int h = getHeight() / 4;
                int size = h * 2;
                int spc = (getHeight() - size) / 2;
                int bg = getWidth() - size - spc - getInsets().right;
                //        if (tiny == null) tiny = getFont().deriveFont(h * 1.2f);
                g.setColor(getBackground());
                g.fillRect(bg - 2, getInsets().top, getWidth() - getInsets().right - bg + 1,
                        getHeight() - getInsets().top - getInsets().bottom);
                if (ci.ascending) {
                    g.setColor(hi1);
                    g.drawLine(bg + h + 1, spc + size - 1, bg + size, spc);
                    g.setColor(hi2);
                    g.drawLine(bg + h + 2, spc + size - 1, bg + size + 1, spc);
                    g.setColor(sh1);
                    g.drawLine(bg, spc, bg + size, spc);
                    g.drawLine(bg + 1, spc, bg + h, spc + size);
                    g.setColor(sh2);
                    g.drawLine(bg, spc, bg + h - 1, spc + size - 1);
                    //          g.setFont(tiny);
                    //          g.setColor(getForeground());
                    //          if (sort.size() > 1) {
                    //            Rectangle2D r = g.getFontMetrics().getStringBounds(String.valueOf(num + 1), g);
                    //
                    //            g.drawString(String.valueOf(num + 1), bg + h - (int) (r.getWidth() / 2),
                    //                         spc + 2 + (int) g.getFontMetrics().getDescent());
                    //          }
                } else {
                    g.setColor(sh1);
                    g.drawLine(bg + h, spc, bg + 1, spc + size - 1);
                    g.setColor(sh2);
                    g.drawLine(bg + h - 1, spc, bg, spc + size - 1);
                    g.setColor(hi1);
                    g.drawLine(bg + 1, spc + size - 1, bg + size, spc + size - 1);
                    g.drawLine(bg + size, spc + size - 1, bg + h + 1, spc);
                    g.setColor(hi2);
                    g.drawLine(bg + size + 1, spc + size - 1, bg + h + 2, spc);
                    //          g.setFont(tiny);
                    //          g.setColor(getForeground());
                    //          if (sort.size() > 1) {
                    //            Rectangle2D r = g.getFontMetrics().getStringBounds(String.valueOf(num + 1), g);
                    //            g.drawString(String.valueOf(num + 1), bg + h - (int) (r.getWidth() / 2), spc + size - 1);
                    //          }
                }
            }
        }
    }

    static class ColumnInfo {
        String colname;
        String[] descs;
        String get;
        DataSet getDs;
        boolean ascending;
        int numgroup;
        static ColumnInfo dummy = new ColumnInfo("");

        static ColumnInfo get(String name) {
            dummy.colname = name;
            return dummy;
        }

        ColumnInfo(String name) {
            colname = name;
            ascending = true;
        }

        ColumnInfo(String name, int group) {
            this(name);
            numgroup = group;
        }

        void toggle() {
            ascending = !ascending;
        }

        public boolean equals(Object o) {
            if (o != null && o instanceof ColumnInfo)
                return colname.equals(((ColumnInfo) o).colname);
            else
                return false;
        }

        public void dump() {
            if (numgroup == 0)
                System.out.println((ascending ? "SORT: " : "SORT(descending): ") + colname);
            else {
                System.out.println(numgroup + ". " + (ascending ? "GROUP: " : "GROUP(descending): ") + colname);
                if (get != null)
                    System.out.println("  print " + VarStr.join(descs, ',') + " from " + get + "()");
            }
        }
    }
}