001/*
002 * Copyright 2010-2015 Institut Pasteur.
003 * 
004 * This file is part of Icy.
005 * 
006 * Icy is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 * 
011 * Icy is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014 * GNU General Public License for more details.
015 * 
016 * You should have received a copy of the GNU General Public License
017 * along with Icy. If not, see <http://www.gnu.org/licenses/>.
018 */
019package icy.util;
020
021import java.io.BufferedReader;
022import java.io.File;
023import java.io.IOException;
024import java.io.StringReader;
025
026import icy.system.IcyExceptionHandler;
027import jxl.Workbook;
028import jxl.format.Colour;
029import jxl.read.biff.BiffException;
030import jxl.write.Label;
031import jxl.write.Number;
032import jxl.write.WritableCellFormat;
033import jxl.write.WritableImage;
034import jxl.write.WritableSheet;
035import jxl.write.WritableWorkbook;
036import jxl.write.WriteException;
037
038/**
039 * XLS (excel) utilities class (create and write XLS documents).<br>
040 * <b>IMPORTANT NOTE</b>: this class only handles basic XLS file, for XLSX files (XML excel)
041 * you need to use the <code>Workbooks</code> plugin (Alexandre Dufour)
042 * 
043 * @author Stephane
044 */
045public class XLSUtil
046{
047    public static final String FILE_EXTENSION = "xls";
048    public static final String FILE_DOT_EXTENSION = "." + FILE_EXTENSION;
049
050    /**
051     * Creates and returns a new Workbook file.<br>
052     * Previous existing file is overwritten.
053     */
054    public static WritableWorkbook createWorkbook(File file) throws IOException
055    {
056        return Workbook.createWorkbook(file);
057    }
058
059    /**
060     * Creates and returns a new Workbook file.<br>
061     * Previous existing file is overwritten.
062     */
063    public static WritableWorkbook createWorkbook(String filename) throws IOException
064    {
065        return createWorkbook(new File(filename));
066    }
067
068    /**
069     * Loads and returns Workbook from an existing file (read operation only)
070     */
071    public static Workbook loadWorkbookForRead(File file) throws IOException, BiffException
072    {
073        return Workbook.getWorkbook(file);
074    }
075
076    /**
077     * Loads and returns Workbook from an existing file (for write operation).<br>
078     * If the file does not exist a new empty Workbook is returned.<br>
079     * <br>
080     * WARNING: don't forget to end by {@link #saveAndClose(WritableWorkbook)} even if you don't
081     * change the Workbook else you lost all previous data already present.
082     */
083    public static WritableWorkbook loadWorkbookForWrite(File file) throws IOException, BiffException
084    {
085        if (!file.exists())
086            return createWorkbook(file);
087
088        return Workbook.createWorkbook(file, Workbook.getWorkbook(file));
089    }
090
091    /**
092     * @deprecated Use {@link #loadWorkbookForRead(File)} or {@link #loadWorkbookForWrite(File)}
093     *             depending your needs.
094     */
095    @Deprecated
096    public static WritableWorkbook loadWorkbook(File file) throws IOException, BiffException
097    {
098        if (!file.exists())
099            return createWorkbook(file);
100
101        final WritableWorkbook result = Workbook.createWorkbook(file, Workbook.getWorkbook(file));
102        // need to do it as the createWorkbook method does erase the old one
103        result.write();
104
105        return result;
106    }
107
108    /**
109     * Saves and closes the specified Workbook.
110     * 
111     * @throws IOException
112     * @throws WriteException
113     */
114    public static void saveAndClose(WritableWorkbook workbook) throws IOException, WriteException
115    {
116        workbook.write();
117        workbook.close();
118    }
119
120    /**
121     * Searches for the specified page in workbook and returns it.<br>
122     * If the page does not exists it creates and returns a new page.<br>
123     * 
124     * @see #createNewPage(WritableWorkbook, String)
125     */
126    public static WritableSheet getPage(WritableWorkbook workbook, String title)
127    {
128        WritableSheet result = workbook.getSheet(title);
129
130        if (result == null)
131            result = workbook.createSheet(title, workbook.getNumberOfSheets() + 1);
132
133        return result;
134    }
135
136    /**
137     * Creates and returns a new page for the specified workbook.<br>
138     * If the page already exists, add an incremented number for distinction.
139     * 
140     * @see #getPage(WritableWorkbook, String)
141     */
142    public static WritableSheet createNewPage(WritableWorkbook workbook, String title)
143    {
144        if (workbook.getSheet(title) == null)
145            return workbook.createSheet(title, workbook.getNumberOfSheets() + 1);
146
147        int counter = 2;
148        while (true)
149        {
150            final String pageName = title + " " + counter;
151
152            if (workbook.getSheet(pageName) == null)
153                return workbook.createSheet(pageName, workbook.getNumberOfSheets() + 1);
154
155            counter++;
156        }
157    }
158
159    /**
160     * Clear the specified workbook (remove all pages).
161     */
162    public static void clear(WritableWorkbook workbook)
163    {
164        while (workbook.getNumberOfSheets() > 0)
165            workbook.removeSheet(workbook.getNumberOfSheets() - 1);
166    }
167
168    /**
169     * Clear the specified page (remove all rows)
170     */
171    public static void clearPage(WritableSheet sheet, String name)
172    {
173        while (sheet.getRows() > 0)
174            sheet.removeRow(sheet.getRows() - 1);
175    }
176
177    /**
178     * Sets name of specified Sheet
179     */
180    public static void setPageName(WritableSheet sheet, String name)
181    {
182        sheet.setName(name);
183    }
184
185    /**
186     * Adds an image to the specified Sheet.<br>
187     * Returns false if the operation failed.
188     */
189    public static boolean addImage(WritableSheet sheet, WritableImage image)
190    {
191        try
192        {
193            sheet.addImage(image);
194            return true;
195        }
196        catch (Exception e)
197        {
198            IcyExceptionHandler.showErrorMessage(e, false, true);
199        }
200
201        return false;
202    }
203
204    /**
205     * Sets cell content in string format of specified Sheet.<br>
206     * Returns false if the operation failed.
207     */
208    public static boolean setCellString(WritableSheet sheet, int x, int y, String value, Colour background)
209    {
210        final WritableCellFormat wcf = new WritableCellFormat();
211
212        try
213        {
214            wcf.setBackground(background);
215        }
216        catch (WriteException e)
217        {
218            // not a fatal error
219            IcyExceptionHandler.showErrorMessage(e, false, true);
220        }
221
222        final Label label = new Label(x, y, value, wcf);
223
224        try
225        {
226            sheet.addCell(label);
227            return true;
228        }
229        catch (Exception e)
230        {
231            IcyExceptionHandler.showErrorMessage(e, false, true);
232        }
233
234        return false;
235    }
236
237    /**
238     * Sets cell content in string format of specified Sheet.<br>
239     * Returns false if the operation failed.
240     */
241    public static boolean setCellString(WritableSheet sheet, int x, int y, String value)
242    {
243        final Label label = new Label(x, y, value);
244
245        try
246        {
247            sheet.addCell(label);
248            return true;
249        }
250        catch (Exception e)
251        {
252            IcyExceptionHandler.showErrorMessage(e, false, true);
253        }
254
255        return false;
256    }
257
258    /**
259     * Sets cell content in double format of specified Sheet.<br>
260     * Returns false if the operation failed.
261     */
262    public static boolean setCellNumber(WritableSheet sheet, int x, int y, double value, Colour background)
263    {
264        final WritableCellFormat wcf = new WritableCellFormat();
265
266        try
267        {
268            wcf.setBackground(background);
269        }
270        catch (WriteException e)
271        {
272            // not a fatal error
273            IcyExceptionHandler.showErrorMessage(e, false, true);
274        }
275
276        final Number number = new Number(x, y, value, wcf);
277
278        try
279        {
280            sheet.addCell(number);
281            return true;
282        }
283        catch (Exception e)
284        {
285            IcyExceptionHandler.showErrorMessage(e, false, true);
286        }
287
288        return false;
289    }
290
291    /**
292     * Sets cell content in double format of specified Sheet.<br>
293     * Returns false if the operation failed.
294     */
295    public static boolean setCellNumber(WritableSheet sheet, int x, int y, double value)
296    {
297        final Number number = new Number(x, y, value);
298
299        try
300        {
301            sheet.addCell(number);
302            return true;
303        }
304        catch (Exception e)
305        {
306            IcyExceptionHandler.showErrorMessage(e, false, true);
307        }
308
309        return false;
310    }
311
312    /**
313     * Fill sheet content from CSV text.
314     * 
315     * @return <code>true</code> if the operation succeed
316     */
317    public static boolean setFromCSV(WritableSheet sheet, String csvContent)
318    {
319        final BufferedReader br = new BufferedReader(new StringReader(csvContent));
320
321        String line;
322        int y = 0;
323        try
324        {
325            while ((line = br.readLine()) != null)
326            {
327                int x = 0;
328
329                // use tab as separator
330                for (String col : line.split("\t"))
331                {
332                    XLSUtil.setCellString(sheet, x, y, col);
333                    x++;
334                }
335
336                y++;
337            }
338
339            return true;
340        }
341        catch (IOException e)
342        {
343            IcyExceptionHandler.showErrorMessage(e, false, true);
344            return false;
345        }
346    }
347}