extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/plugins/QubitSampleNameExporter.java

Code
Comments
Other
Rev Date Author Line
1900 07 Mar 13 nicklas 1 package net.sf.basedb.reggie.plugins;
1900 07 Mar 13 nicklas 2
1900 07 Mar 13 nicklas 3 import java.io.IOException;
5297 13 Feb 19 nicklas 4 import java.io.OutputStream;
1900 07 Mar 13 nicklas 5 import java.io.OutputStreamWriter;
1900 07 Mar 13 nicklas 6 import java.io.Writer;
1900 07 Mar 13 nicklas 7 import java.util.ArrayList;
1900 07 Mar 13 nicklas 8 import java.util.Arrays;
1900 07 Mar 13 nicklas 9 import java.util.Collections;
5298 13 Feb 19 nicklas 10 import java.util.Date;
1900 07 Mar 13 nicklas 11 import java.util.Iterator;
1900 07 Mar 13 nicklas 12 import java.util.List;
1900 07 Mar 13 nicklas 13 import java.util.Set;
1900 07 Mar 13 nicklas 14
5371 16 Apr 19 nicklas 15 import org.apache.poi.ss.usermodel.CellStyle;
5371 16 Apr 19 nicklas 16 import org.apache.poi.ss.usermodel.Font;
5298 13 Feb 19 nicklas 17 import org.apache.poi.ss.usermodel.IndexedColors;
5371 16 Apr 19 nicklas 18 import org.apache.poi.ss.usermodel.Sheet;
5298 13 Feb 19 nicklas 19
1900 07 Mar 13 nicklas 20 import net.sf.basedb.core.BaseException;
1900 07 Mar 13 nicklas 21 import net.sf.basedb.core.BioMaterial;
1900 07 Mar 13 nicklas 22 import net.sf.basedb.core.BioPlate;
1900 07 Mar 13 nicklas 23 import net.sf.basedb.core.BioWell;
1900 07 Mar 13 nicklas 24 import net.sf.basedb.core.DbControl;
1900 07 Mar 13 nicklas 25 import net.sf.basedb.core.Item;
1900 07 Mar 13 nicklas 26 import net.sf.basedb.core.ItemParameterType;
1900 07 Mar 13 nicklas 27 import net.sf.basedb.core.ItemQuery;
1900 07 Mar 13 nicklas 28 import net.sf.basedb.core.Path;
1900 07 Mar 13 nicklas 29 import net.sf.basedb.core.PermissionDeniedException;
1900 07 Mar 13 nicklas 30 import net.sf.basedb.core.PluginDefinition;
1900 07 Mar 13 nicklas 31 import net.sf.basedb.core.PluginParameter;
1900 07 Mar 13 nicklas 32 import net.sf.basedb.core.ProgressReporter;
1900 07 Mar 13 nicklas 33 import net.sf.basedb.core.RequestInformation;
5298 13 Feb 19 nicklas 34 import net.sf.basedb.core.StringParameterType;
1900 07 Mar 13 nicklas 35 import net.sf.basedb.core.Job.ExecutionTime;
1900 07 Mar 13 nicklas 36 import net.sf.basedb.core.plugin.AbstractExporterPlugin;
1900 07 Mar 13 nicklas 37 import net.sf.basedb.core.plugin.ExportOutputStream;
1900 07 Mar 13 nicklas 38 import net.sf.basedb.core.plugin.GuiContext;
1900 07 Mar 13 nicklas 39 import net.sf.basedb.core.plugin.InteractivePlugin;
1900 07 Mar 13 nicklas 40 import net.sf.basedb.core.plugin.Request;
1900 07 Mar 13 nicklas 41 import net.sf.basedb.core.plugin.Response;
1900 07 Mar 13 nicklas 42 import net.sf.basedb.core.query.Hql;
1900 07 Mar 13 nicklas 43 import net.sf.basedb.core.query.Orders;
5298 13 Feb 19 nicklas 44 import net.sf.basedb.reggie.Reggie;
5371 16 Apr 19 nicklas 45 import net.sf.basedb.util.excel.CellStyleCreator;
5371 16 Apr 19 nicklas 46 import net.sf.basedb.util.excel.XlsxTableWriter;
5371 16 Apr 19 nicklas 47 import net.sf.basedb.util.excel.XlsxToCsvUtil;
1900 07 Mar 13 nicklas 48 import net.sf.basedb.util.export.TableWriter;
1900 07 Mar 13 nicklas 49
1900 07 Mar 13 nicklas 50 /**
1900 07 Mar 13 nicklas 51   Plug-in for exporting biomaterial names for each well on a plate.
1900 07 Mar 13 nicklas 52   This class can be used as a BASE plug-in or as a standalone exporter.
1900 07 Mar 13 nicklas 53   In the latter case, simply use the {@link #exportSampleNames(DbControl, BioPlate, Writer)}
1900 07 Mar 13 nicklas 54   method.
1900 07 Mar 13 nicklas 55   <p>
1900 07 Mar 13 nicklas 56   
1900 07 Mar 13 nicklas 57   Since the exporter should be really quick it doesn't implement support for aborting
1900 07 Mar 13 nicklas 58   or progress reporting.
1900 07 Mar 13 nicklas 59   
1900 07 Mar 13 nicklas 60   @author nicklas
1900 07 Mar 13 nicklas 61   @since 2.12
1900 07 Mar 13 nicklas 62 */
1900 07 Mar 13 nicklas 63 public class QubitSampleNameExporter 
1900 07 Mar 13 nicklas 64   extends AbstractExporterPlugin 
1900 07 Mar 13 nicklas 65   implements InteractivePlugin
1900 07 Mar 13 nicklas 66 {
1900 07 Mar 13 nicklas 67
1900 07 Mar 13 nicklas 68   private RequestInformation configureJob;
1900 07 Mar 13 nicklas 69   
1900 07 Mar 13 nicklas 70   public QubitSampleNameExporter()
1900 07 Mar 13 nicklas 71   {}
1900 07 Mar 13 nicklas 72   
1900 07 Mar 13 nicklas 73   /*
1900 07 Mar 13 nicklas 74      From the Plugin interface
1900 07 Mar 13 nicklas 75      --------------------------------
1900 07 Mar 13 nicklas 76   */
1900 07 Mar 13 nicklas 77   @Override
1900 07 Mar 13 nicklas 78   public boolean supportsConfigurations()
1900 07 Mar 13 nicklas 79   {
1900 07 Mar 13 nicklas 80     return false;
1900 07 Mar 13 nicklas 81   }
1900 07 Mar 13 nicklas 82   @Override
1900 07 Mar 13 nicklas 83   public boolean requiresConfiguration()
1900 07 Mar 13 nicklas 84   {
1900 07 Mar 13 nicklas 85     return false;
1900 07 Mar 13 nicklas 86   }
1900 07 Mar 13 nicklas 87   // -------------------------------------
1900 07 Mar 13 nicklas 88   
1900 07 Mar 13 nicklas 89   /*
1900 07 Mar 13 nicklas 90      From the InteractivePlugin interface
1900 07 Mar 13 nicklas 91      -------------------------------------------
1900 07 Mar 13 nicklas 92   */
1900 07 Mar 13 nicklas 93   /**
1900 07 Mar 13 nicklas 94     The plug-in will appear on the 
1900 07 Mar 13 nicklas 95    */
1900 07 Mar 13 nicklas 96   @Override
1900 07 Mar 13 nicklas 97   public Set<GuiContext> getGuiContexts()
1900 07 Mar 13 nicklas 98   {
1900 07 Mar 13 nicklas 99     return Collections.singleton(GuiContext.item(Item.BIOPLATE));
1900 07 Mar 13 nicklas 100   }
1900 07 Mar 13 nicklas 101   /**
1900 07 Mar 13 nicklas 102     We accept all bioplates.
1900 07 Mar 13 nicklas 103   */
1900 07 Mar 13 nicklas 104   @Override
1900 07 Mar 13 nicklas 105   public String isInContext(GuiContext context, Object item)
1900 07 Mar 13 nicklas 106   {
1900 07 Mar 13 nicklas 107     String message = null;
1900 07 Mar 13 nicklas 108     if (item == null)
1900 07 Mar 13 nicklas 109     {
1900 07 Mar 13 nicklas 110       message = "The object is null";
1900 07 Mar 13 nicklas 111     }
1900 07 Mar 13 nicklas 112     else if (!(item instanceof BioPlate))
1900 07 Mar 13 nicklas 113     {
1900 07 Mar 13 nicklas 114       message = "The object is not a BioPlate: " + item;
1900 07 Mar 13 nicklas 115     }
1900 07 Mar 13 nicklas 116     return message;
1900 07 Mar 13 nicklas 117   }
1900 07 Mar 13 nicklas 118   @Override
1900 07 Mar 13 nicklas 119   public RequestInformation getRequestInformation(GuiContext context, String command) 
1900 07 Mar 13 nicklas 120     throws BaseException
1900 07 Mar 13 nicklas 121   {
1900 07 Mar 13 nicklas 122     RequestInformation requestInformation = null;
1900 07 Mar 13 nicklas 123     if (Request.COMMAND_CONFIGURE_JOB.equals(command))
1900 07 Mar 13 nicklas 124     {
1900 07 Mar 13 nicklas 125       requestInformation = getConfigureJobParameters(null);
1900 07 Mar 13 nicklas 126     }
1900 07 Mar 13 nicklas 127     return requestInformation;
1900 07 Mar 13 nicklas 128   }
1900 07 Mar 13 nicklas 129   @Override
1900 07 Mar 13 nicklas 130   public void configure(GuiContext context, Request request, Response response)
1900 07 Mar 13 nicklas 131   {
1900 07 Mar 13 nicklas 132     String command = request.getCommand();    
1900 07 Mar 13 nicklas 133     try
1900 07 Mar 13 nicklas 134     {
1900 07 Mar 13 nicklas 135       if (command.equals(Request.COMMAND_CONFIGURE_JOB))
1900 07 Mar 13 nicklas 136       {
1900 07 Mar 13 nicklas 137         RequestInformation ri = getConfigureJobParameters(!request.isAllowedImmediateExecution());
1900 07 Mar 13 nicklas 138         List<Throwable> errors = validateRequestParameters(ri.getParameters(), request);
1900 07 Mar 13 nicklas 139         if (errors != null)
1900 07 Mar 13 nicklas 140         {
1900 07 Mar 13 nicklas 141           response.setError(errors.size() + " invalid parameters were found in the request",errors);
1900 07 Mar 13 nicklas 142           return;
1900 07 Mar 13 nicklas 143         }        
1900 07 Mar 13 nicklas 144         
1900 07 Mar 13 nicklas 145         storeValue(job, request, ri.getParameter("bioplate"));
5298 13 Feb 19 nicklas 146         storeValue(job, request, ri.getParameter("format"));
1900 07 Mar 13 nicklas 147         if (request.getParameterValue(SAVE_AS) == null)
1900 07 Mar 13 nicklas 148         {
1900 07 Mar 13 nicklas 149           if (!request.isAllowedImmediateExecution())
1900 07 Mar 13 nicklas 150           {
1900 07 Mar 13 nicklas 151             response.setError("Immediate download is not allowed. Please specify a filename.", null);
1900 07 Mar 13 nicklas 152             return;
1900 07 Mar 13 nicklas 153           }
1900 07 Mar 13 nicklas 154           BioPlate plate = (BioPlate)request.getParameterValue("bioplate");
1900 07 Mar 13 nicklas 155           response.setDownloadImmediately("Export Qubit sample names for bioplate " + 
1900 07 Mar 13 nicklas 156               plate.getName(), ExecutionTime.SHORTEST, true);
1900 07 Mar 13 nicklas 157         }
1900 07 Mar 13 nicklas 158         else
1900 07 Mar 13 nicklas 159         {
1900 07 Mar 13 nicklas 160           Object parameterValue = request.getParameterValue(OVERWRITE); 
1900 07 Mar 13 nicklas 161           boolean overwrite = parameterValue != null ? (Boolean)parameterValue : false;
1900 07 Mar 13 nicklas 162           if (!pathCanBeUsed((String)request.getParameterValue(ri.getParameter(SAVE_AS).getName()), overwrite))
1900 07 Mar 13 nicklas 163           {
1900 07 Mar 13 nicklas 164             response.setError("File exists: " + (String)request.getParameterValue(ri.getParameter(SAVE_AS).getName()), null);
1900 07 Mar 13 nicklas 165             return;
1900 07 Mar 13 nicklas 166           }
1900 07 Mar 13 nicklas 167           storeValue(job, request, ri.getParameter(SAVE_AS));
1900 07 Mar 13 nicklas 168           storeValue(job, request, ri.getParameter(OVERWRITE));
1900 07 Mar 13 nicklas 169           BioPlate plate = (BioPlate)job.getValue("bioplate");
1900 07 Mar 13 nicklas 170           response.setSuggestedJobName("Export Qubit sample names for bioplate '" + plate.getName() + "'");
1900 07 Mar 13 nicklas 171           response.setDone("The job configuration is complete", ExecutionTime.SHORTEST);
1900 07 Mar 13 nicklas 172         }
1900 07 Mar 13 nicklas 173       }
1900 07 Mar 13 nicklas 174     }
1900 07 Mar 13 nicklas 175     catch(Throwable ex)
1900 07 Mar 13 nicklas 176     {
1900 07 Mar 13 nicklas 177       response.setError(ex.getMessage(), Arrays.asList(ex));
1900 07 Mar 13 nicklas 178     }    
1900 07 Mar 13 nicklas 179   }
1900 07 Mar 13 nicklas 180   // ------------------------------------------------
1900 07 Mar 13 nicklas 181   
1900 07 Mar 13 nicklas 182   
1900 07 Mar 13 nicklas 183   /*
1900 07 Mar 13 nicklas 184     From the AbstractExporterPlugin interface
1900 07 Mar 13 nicklas 185     -----------------------------------------
1900 07 Mar 13 nicklas 186   */
1900 07 Mar 13 nicklas 187   private DbControl dc;
1900 07 Mar 13 nicklas 188   private int numExported;
1900 07 Mar 13 nicklas 189   @Override
1900 07 Mar 13 nicklas 190   protected void begin(DbControl dc)
1900 07 Mar 13 nicklas 191   {
1900 07 Mar 13 nicklas 192     this.dc = dc;
1900 07 Mar 13 nicklas 193   }
1900 07 Mar 13 nicklas 194
1900 07 Mar 13 nicklas 195   @Override
1900 07 Mar 13 nicklas 196   protected void performExport(ExportOutputStream out, ProgressReporter progress) 
1900 07 Mar 13 nicklas 197     throws IOException 
1900 07 Mar 13 nicklas 198   {
5298 13 Feb 19 nicklas 199     String format = (String)job.getValue("format");
5298 13 Feb 19 nicklas 200     if ("xlsx".equals(format))
5298 13 Feb 19 nicklas 201     {
5298 13 Feb 19 nicklas 202       if (progress != null) progress.display(5, "Exporting to Excel file...");
5371 16 Apr 19 nicklas 203       out.setMimeType(XlsxToCsvUtil.XLSX_MIME_TYPE);
5298 13 Feb 19 nicklas 204     }
5298 13 Feb 19 nicklas 205     else
5298 13 Feb 19 nicklas 206     {
5298 13 Feb 19 nicklas 207       if (progress != null) progress.display(5, "Exporting to CSV file...");
5298 13 Feb 19 nicklas 208       format = "csv";
5298 13 Feb 19 nicklas 209       out.setMimeType("text/csv");
5298 13 Feb 19 nicklas 210       out.setCharacterSet("UTF-8");
5298 13 Feb 19 nicklas 211     }
1900 07 Mar 13 nicklas 212     
1900 07 Mar 13 nicklas 213     BioPlate plate = (BioPlate)job.getValue("bioplate");
1900 07 Mar 13 nicklas 214     plate = BioPlate.getById(dc, plate.getId());
1900 07 Mar 13 nicklas 215     out.setMimeType("text/csv");
5298 13 Feb 19 nicklas 216     String filename = Path.makeSafeFilename(plate.getName(), "")+"-qubit."+format;
1900 07 Mar 13 nicklas 217     out.setFilename(filename);
1900 07 Mar 13 nicklas 218     
5298 13 Feb 19 nicklas 219     numExported = exportSampleNames(dc, plate, out, format);
5297 13 Feb 19 nicklas 220     out.flush();
5298 13 Feb 19 nicklas 221     if (progress != null) progress.display(100, "File created successfully");
1900 07 Mar 13 nicklas 222   }
5297 13 Feb 19 nicklas 223   
1900 07 Mar 13 nicklas 224   @Override
1900 07 Mar 13 nicklas 225   protected void end(boolean success)
1900 07 Mar 13 nicklas 226   {
1900 07 Mar 13 nicklas 227     this.dc = null;
1900 07 Mar 13 nicklas 228   }
1900 07 Mar 13 nicklas 229   @Override
1900 07 Mar 13 nicklas 230   protected String getSuccessMessage()
1900 07 Mar 13 nicklas 231   {
1900 07 Mar 13 nicklas 232     return numExported + " sample names exported successfully";
1900 07 Mar 13 nicklas 233   }
1900 07 Mar 13 nicklas 234   // -------------------------------------------
1900 07 Mar 13 nicklas 235   
1900 07 Mar 13 nicklas 236   private RequestInformation getConfigureJobParameters(Boolean requireFile)
1900 07 Mar 13 nicklas 237   {
1900 07 Mar 13 nicklas 238     if (configureJob == null)
1900 07 Mar 13 nicklas 239     {
1900 07 Mar 13 nicklas 240       // Load the current bioplate
1900 07 Mar 13 nicklas 241       BioPlate currentPlate = null;
1900 07 Mar 13 nicklas 242       int currentPlateId = sc.getCurrentContext(Item.BIOPLATE).getId();
1900 07 Mar 13 nicklas 243       if (currentPlateId != 0)
1900 07 Mar 13 nicklas 244       {
1900 07 Mar 13 nicklas 245         DbControl dc = sc.newDbControl();
1900 07 Mar 13 nicklas 246         try
1900 07 Mar 13 nicklas 247         {
1900 07 Mar 13 nicklas 248           currentPlate = BioPlate.getById(dc, currentPlateId);
1900 07 Mar 13 nicklas 249         }
1900 07 Mar 13 nicklas 250         finally
1900 07 Mar 13 nicklas 251         {
1900 07 Mar 13 nicklas 252           if (dc != null) dc.close();
1900 07 Mar 13 nicklas 253         }
1900 07 Mar 13 nicklas 254       }
1900 07 Mar 13 nicklas 255       
1900 07 Mar 13 nicklas 256       List<PluginParameter<?>> parameters = new ArrayList<PluginParameter<?>>();
1900 07 Mar 13 nicklas 257
1900 07 Mar 13 nicklas 258       parameters.add(new PluginParameter<BioPlate>(
1900 07 Mar 13 nicklas 259         "bioplate", "Bioplate", "Select the bioplate to export", 
1900 07 Mar 13 nicklas 260         new ItemParameterType<BioPlate>(BioPlate.class, currentPlate, true, 1, null)
1900 07 Mar 13 nicklas 261       ));
1900 07 Mar 13 nicklas 262       
1900 07 Mar 13 nicklas 263       if (requireFile == null)
1900 07 Mar 13 nicklas 264       {
1900 07 Mar 13 nicklas 265         PluginDefinition pd = job.getPluginDefinition();
1900 07 Mar 13 nicklas 266         requireFile = pd == null ? false : !pd.getAllowImmediateExecution();
1900 07 Mar 13 nicklas 267       }
1900 07 Mar 13 nicklas 268       String defaultPath = null;
1900 07 Mar 13 nicklas 269       if (requireFile && currentPlate != null)
1900 07 Mar 13 nicklas 270       {
1900 07 Mar 13 nicklas 271         defaultPath = "~/" + Path.makeSafeFilename(currentPlate.getName(), "") + ".csv";
1900 07 Mar 13 nicklas 272       }
5298 13 Feb 19 nicklas 273       
5298 13 Feb 19 nicklas 274       parameters.add(new PluginParameter<String>("format", "File format", 
5298 13 Feb 19 nicklas 275         "The exporter supports tab-seprated (csv) files and Excel (xslx).",
5298 13 Feb 19 nicklas 276         new StringParameterType(255, "csv", true, 1, 1, 1, Arrays.asList("csv", "xlsx"))
5298 13 Feb 19 nicklas 277           ));
5298 13 Feb 19 nicklas 278       
1900 07 Mar 13 nicklas 279       parameters.add(getSaveAsParameter(null, null, defaultPath, requireFile));
1900 07 Mar 13 nicklas 280       parameters.add(getOverwriteParameter(null, null));
1900 07 Mar 13 nicklas 281       
1900 07 Mar 13 nicklas 282       configureJob = new RequestInformation
1900 07 Mar 13 nicklas 283       (
1900 07 Mar 13 nicklas 284         Request.COMMAND_CONFIGURE_JOB,
1900 07 Mar 13 nicklas 285         "Qubit export options",
1900 07 Mar 13 nicklas 286         "Select bioplate and the file path where the export file should be saved",
1900 07 Mar 13 nicklas 287         parameters
1900 07 Mar 13 nicklas 288       );
1900 07 Mar 13 nicklas 289     }
1900 07 Mar 13 nicklas 290     return configureJob;
1900 07 Mar 13 nicklas 291   }
1900 07 Mar 13 nicklas 292
1900 07 Mar 13 nicklas 293   /**
1900 07 Mar 13 nicklas 294     Export sample names from the given bioplate. The data is written
1900 07 Mar 13 nicklas 295     to the given writer formatted in tab-separated columns in the following
1900 07 Mar 13 nicklas 296     order: Well coordinate sorted by column, sample name, empty column for 
1900 07 Mar 13 nicklas 297     concentration.
1900 07 Mar 13 nicklas 298     @return The number of samples exported
1900 07 Mar 13 nicklas 299   */
5297 13 Feb 19 nicklas 300   public int exportSampleNames(DbControl dc, BioPlate plate, OutputStream out, String format)
1900 07 Mar 13 nicklas 301     throws IOException
1900 07 Mar 13 nicklas 302   {
1900 07 Mar 13 nicklas 303     int numExported = 0;
1900 07 Mar 13 nicklas 304     
1900 07 Mar 13 nicklas 305     //Query to get all non-empty wells on the plate
1900 07 Mar 13 nicklas 306     ItemQuery<BioWell> query = plate.getBioWells();
1900 07 Mar 13 nicklas 307     // Load only non-empty wells
1900 07 Mar 13 nicklas 308     query.join(Hql.innerJoin(null, "bioMaterial", "bm", true));
1900 07 Mar 13 nicklas 309     query.order(Orders.asc(Hql.property("column")));
1900 07 Mar 13 nicklas 310     query.order(Orders.asc(Hql.property("row")));
1900 07 Mar 13 nicklas 311     
1900 07 Mar 13 nicklas 312     // Wrap the output writer in a table writer
5297 13 Feb 19 nicklas 313     TableWriter tw = null;
5297 13 Feb 19 nicklas 314     XlsxTableWriter xls = null;
5371 16 Apr 19 nicklas 315     CellStyleCreator styleCreator = null;
5297 13 Feb 19 nicklas 316     if ("xlsx".equals(format))
5297 13 Feb 19 nicklas 317     {
5297 13 Feb 19 nicklas 318       // This is safe as long as we only use the TableWriter.tablePrintData() method
5297 13 Feb 19 nicklas 319       xls = new XlsxTableWriter("Qubit");
5297 13 Feb 19 nicklas 320       tw = xls;
5371 16 Apr 19 nicklas 321       styleCreator = createStyles(xls);
5297 13 Feb 19 nicklas 322     }
5297 13 Feb 19 nicklas 323     else
5297 13 Feb 19 nicklas 324     {
5297 13 Feb 19 nicklas 325       tw = new TableWriter(new OutputStreamWriter(out, "UTF-8"));
5297 13 Feb 19 nicklas 326       tw.setDataSeparator("\t"); // Tab-separated file
5297 13 Feb 19 nicklas 327       tw.setNullValue("");
5297 13 Feb 19 nicklas 328       // Get rid of "bad" characters (comma, tab, newline, etc.)
5297 13 Feb 19 nicklas 329       tw.setEncoder(new CsvEncoderDecoder());
5297 13 Feb 19 nicklas 330     }
1900 07 Mar 13 nicklas 331     
5371 16 Apr 19 nicklas 332     if (styleCreator != null) styleCreator.setBaseStyle(commentStyle);
5298 13 Feb 19 nicklas 333     tw.tablePrintData("#");
5298 13 Feb 19 nicklas 334     tw.tablePrintData("# Qubit Sample Name file for "+ plate.getName());
5298 13 Feb 19 nicklas 335     tw.tablePrintData("# Created by Reggie " + Reggie.VERSION);
5298 13 Feb 19 nicklas 336     tw.tablePrintData("# Created at " + Reggie.CONVERTER_DATETIME_TO_STRING_WITH_SEPARATOR.convert(new Date()));
5298 13 Feb 19 nicklas 337     tw.tablePrintData("#");
1930 16 Apr 13 nicklas 338     tw.tablePrintData("# Enter concentration measurements in nanogram/milliliter");
1930 16 Apr 13 nicklas 339     tw.tablePrintData("# All extracts should have an 'Qubit ng/ml' value");
1925 11 Apr 13 nicklas 340     tw.tablePrintData("# Extracts that have been SpeedVac:ed should have ");
1925 11 Apr 13 nicklas 341     tw.tablePrintData("# a second measurement made after the SpeedVac");
1925 11 Apr 13 nicklas 342     tw.tablePrintData("#");
5371 16 Apr 19 nicklas 343     if (styleCreator != null) styleCreator.setBaseStyle(headerStyle);
1930 16 Apr 13 nicklas 344     tw.tablePrintData("Well", "Library name", "Qubit ng/ml", "After SpeedVac");
5371 16 Apr 19 nicklas 345     if (styleCreator != null) styleCreator.setBaseStyle(null);
1900 07 Mar 13 nicklas 346     Iterator<BioWell> it = query.iterate(dc);
1925 11 Apr 13 nicklas 347     int lastCol = -1;
1900 07 Mar 13 nicklas 348     while (it.hasNext())
1900 07 Mar 13 nicklas 349     {
1900 07 Mar 13 nicklas 350       BioWell well = it.next();
1925 11 Apr 13 nicklas 351       if (lastCol != -1 && lastCol != well.getColumn())
1925 11 Apr 13 nicklas 352       {
5371 16 Apr 19 nicklas 353         if (styleCreator != null) styleCreator.setBaseStyle(commentStyle);
1925 11 Apr 13 nicklas 354         tw.tablePrintData("#");
5371 16 Apr 19 nicklas 355         if (styleCreator != null) styleCreator.setBaseStyle(null);
1925 11 Apr 13 nicklas 356       }
1925 11 Apr 13 nicklas 357       lastCol = well.getColumn();
1900 07 Mar 13 nicklas 358       BioMaterial bm = null;
1900 07 Mar 13 nicklas 359       try
1900 07 Mar 13 nicklas 360       {
1900 07 Mar 13 nicklas 361         bm = well.getBioMaterial();
1900 07 Mar 13 nicklas 362         tw.tablePrintData(well.getCoordinate(), bm.getName(), "");
1900 07 Mar 13 nicklas 363         numExported++;
1900 07 Mar 13 nicklas 364       }
1900 07 Mar 13 nicklas 365       catch (PermissionDeniedException ex)
1900 07 Mar 13 nicklas 366       {}
1900 07 Mar 13 nicklas 367     }
1900 07 Mar 13 nicklas 368     
5297 13 Feb 19 nicklas 369     if (xls != null)
5297 13 Feb 19 nicklas 370     {
5371 16 Apr 19 nicklas 371       Sheet sheet = xls.getSheet();
5298 13 Feb 19 nicklas 372       sheet.setColumnWidth(0, 10*256);
5298 13 Feb 19 nicklas 373       sheet.setColumnWidth(1, 30*256);
5298 13 Feb 19 nicklas 374       sheet.setColumnWidth(2, 15*256);
5298 13 Feb 19 nicklas 375       sheet.setColumnWidth(3, 15*256);
5297 13 Feb 19 nicklas 376       xls.saveTo(out);
5297 13 Feb 19 nicklas 377       xls.close();
5297 13 Feb 19 nicklas 378     }
5297 13 Feb 19 nicklas 379     
1900 07 Mar 13 nicklas 380     tw.flush();
1900 07 Mar 13 nicklas 381     out.flush();
1900 07 Mar 13 nicklas 382     return numExported;
1900 07 Mar 13 nicklas 383   }
5298 13 Feb 19 nicklas 384   
5371 16 Apr 19 nicklas 385   private CellStyle commentStyle;
5371 16 Apr 19 nicklas 386   private CellStyle headerStyle;
5371 16 Apr 19 nicklas 387     private CellStyleCreator createStyles(XlsxTableWriter xls)
5298 13 Feb 19 nicklas 388     {
5371 16 Apr 19 nicklas 389       CellStyleCreator styleCreator = xls.getCellStyleCreator();
5371 16 Apr 19 nicklas 390     Font italicGrey = styleCreator.createFont();
5371 16 Apr 19 nicklas 391     italicGrey.setItalic(true);
5371 16 Apr 19 nicklas 392     italicGrey.setColor(IndexedColors.GREY_50_PERCENT.getIndex());
5371 16 Apr 19 nicklas 393     commentStyle = styleCreator.createStyle();
5371 16 Apr 19 nicklas 394     commentStyle.setFont(italicGrey);
5298 13 Feb 19 nicklas 395     
5371 16 Apr 19 nicklas 396     Font bold = styleCreator.createFont();
5371 16 Apr 19 nicklas 397     bold.setBold(true);
5371 16 Apr 19 nicklas 398     headerStyle = styleCreator.createStyle();
5371 16 Apr 19 nicklas 399     headerStyle.setFont(bold);
5371 16 Apr 19 nicklas 400     
5371 16 Apr 19 nicklas 401     return styleCreator;
5298 13 Feb 19 nicklas 402     }
1900 07 Mar 13 nicklas 403 }