public static ExcelPackage MergeWorkbooks(ExcelPackage srcExcel, ExcelPackage destExcel, Dictionary <string, string> options) { var(startRow, startCol) = ExcelUtils.GetRowCol(options["StartInCell"]); // Merge one sheet at a time foreach (var srcSheet in srcExcel.Workbook.Worksheets) { var sheetName = srcSheet.Name; var destSheet = destExcel.Workbook.Worksheets[sheetName]; // Read source sheet into map if (options["SamplesIn"] == "rows") { // Location of sample and compound names var compoundRow = ExcelUtils.GetRowNum(options["CompoundLoc"]); var sampleCol = ExcelUtils.GetColNum(options["SampleLoc"]); // Read source sheet data var srcMap = ExcelToMap.SamplesInRowsToMap(compoundRow, sampleCol, srcExcel, sheetName); // Row to start writing data in destination sheet var nextEmptyRow = ExcelUtils.RowsInColumn(destSheet, sampleCol) + 1; // Write into destination sheet // Write sample names destExcel = MapToExcel.WriteSamplesInRows(srcMap, destExcel, sheetName, sampleCol, nextEmptyRow); // Write data into template destExcel = MapToExcel.WriteIntoTemplate(srcMap, destExcel, options, sheetName, false, nextEmptyRow, startCol, sampleCol, compoundRow); } } return(destExcel); }
// Data Reproducibility // Copy "Relative Quant Data" tab, remove all non-QC // Absolute Quant Calc with template public static ExcelPackage AbsoluteQuantCalc( ExcelPackage excelPkg, Dictionary <string, string> options, int compoundLoc) { var calcSheet = excelPkg.Workbook.Worksheets[options["AbsoluteQuantTabName"]]; var writeSheet = excelPkg.Workbook.Worksheets["Absolute Quant Data"]; OrderedDictionary concMap = new OrderedDictionary(); // Get approximate bounds var rows = ExcelUtils.RowsInColumn(calcSheet, compoundLoc); var cols = ExcelUtils.ColumnsInRow(calcSheet, 1); // Fill in formulas and calculate concentration for (int row = 4; row <= rows; ++row) { // Calculate row with "Concentration (uM)" var compound = calcSheet.Cells[row, compoundLoc]?.Value?.ToString(); if ("Concentration (uM)".Equals(compound)) { // Change "Concentration (uM)" to compound name compound = calcSheet.Cells[row - 2, compoundLoc]?.Value?.ToString(); calcSheet.Cells[row, compoundLoc].Value = compound; if (!concMap.Contains(compound)) { concMap.Add(compound, new OrderedDictionary()); } // Copy formula into empty cells and calculate for (int col = 2; col <= cols; ++col) { var cell = calcSheet.Cells[row, col]?.Value?.ToString(); if (cell is null || cell.Length < 1) { calcSheet.Cells[row, col - 1].Copy(calcSheet.Cells[row, col]); } calcSheet.Cells[row, col].Calculate(); try { var sampleName = calcSheet.Cells[1, col]?.Value?.ToString(); if (sampleName is null || sampleName == "Compound") { continue; } if (((OrderedDictionary)concMap[compound]).Contains(sampleName)) { sampleName = Merge.RenameDuplicate(((OrderedDictionary)concMap[compound]).Keys, sampleName); } var conc = calcSheet.Cells[row, col]?.Value?.ToString(); ((OrderedDictionary)concMap[compound]).Add(sampleName, conc); } catch { } } } } // Save calculations //excelPkg.SaveAs(new FileInfo(options["OutputFolder"] + "\\" + options["OutputFileName"])); excelPkg.Save(); // Write concentrations to "Absolute Quant Data" tab excelPkg = MapToExcel.WriteIntoTemplate(concMap, excelPkg, options, "Absolute Quant Data"); // Format to 3 decimal places var writeCols = ExcelUtils.ColumnsInRow(writeSheet, 1); writeSheet.Cells[1, 4, 31, writeCols].Style.Numberformat.Format = "0.000"; //calcSheet.Hidden = eWorkSheetHidden.Hidden; //excelPkg.SaveAs(new FileInfo(options["OutputFolder"] + "\\" + options["OutputFileName"])); excelPkg.Save(); //progressPage.ProgressTextBox.AppendText("Finished writing into template\n"); return(excelPkg); }
/// <summary> /// Absolute Quant Calc with Sciex 6500 template /// </summary> /// <param name="excelPkg"></param> /// <param name="options"></param> /// <param name="compoundLoc"></param> /// <returns></returns> public static ExcelPackage Sciex6500Template( ExcelPackage excelPkg, Dictionary <string, string> options, int compoundLoc) { var calcSheet = excelPkg.Workbook.Worksheets[options["AbsoluteQuantTabName"]]; var writeSheet = excelPkg.Workbook.Worksheets["Absolute Quant Data"]; OrderedDictionary concMap = new OrderedDictionary(); // Get approximate bounds var rows = ExcelUtils.RowsInColumn(calcSheet, compoundLoc); var cols = ExcelUtils.ColumnsInRow(calcSheet, 1); // Fill in formulas and calculate concentration for (int row = 4; row <= rows; ++row) { // Calculate row with "Concentration (uM)" var compound = calcSheet.Cells[row, compoundLoc]?.Value?.ToString(); if ("Concentration (uM)".Equals(compound)) { // Change "Concentration (uM)" to compound name compound = calcSheet.Cells[row - 2, compoundLoc]?.Value?.ToString(); calcSheet.Cells[row, compoundLoc].Value = compound; if (!concMap.Contains(compound)) { concMap.Add(compound, new OrderedDictionary()); } // Copy formula into empty cells and calculate for (int col = 2; col <= cols; ++col) { var cell = calcSheet.Cells[row, col]?.Value?.ToString(); if (cell is null || cell.Length < 1) { calcSheet.Cells[row, col - 1].Copy(calcSheet.Cells[row, col]); } calcSheet.Cells[row, col].Calculate(); try { var sampleName = calcSheet.Cells[1, col]?.Value?.ToString(); if (sampleName is null || sampleName == "Compound") { continue; } if (((OrderedDictionary)concMap[compound]).Contains(sampleName)) { sampleName = Merge.RenameDuplicate(((OrderedDictionary)concMap[compound]).Keys, sampleName); } var conc = calcSheet.Cells[row, col]?.Value?.ToString(); ((OrderedDictionary)concMap[compound]).Add(sampleName, conc); } catch { } } } } // Save calculations excelPkg.Save(); // Write concentrations to "Absolute Quant Data" tab excelPkg = MapToExcel.WriteIntoTemplate(concMap, excelPkg, options, "Absolute Quant Data"); // Format to 3 decimal places var writeCols = ExcelUtils.ColumnsInRow(writeSheet, 1); writeSheet.Cells[1, 4, 31, writeCols].Style.Numberformat.Format = "0.000"; excelPkg.Save(); // Insert CV columns for QC excelPkg = QualityControl.InsertCVColumns(excelPkg, options, "Absolute Quant Data"); excelPkg.Save(); // Replace missing values with N/A excelPkg = MissingValue.ReplaceMissing(excelPkg, "Absolute Quant Data", "N/A", options["StartInCell"]); excelPkg.Save(); // Write "Absolute Concentration (mM or micromoles/Liter)" above samples return(excelPkg); }
/// <summary> /// /// </summary> /// <param name="excelPkg"></param> /// <param name="options"></param> /// <param name="tabName"></param> /// <returns></returns> public static ExcelPackage InsertCVRows(ExcelPackage excelPkg, Dictionary <string, string> options, string tabName) { var worksheet = excelPkg.Workbook.Worksheets[tabName]; var(nameCol, startRow) = GetNameLocStartLoc( "rows", options["WriteDataInTemplate"], options["SampleLoc"], options["StartInCell"]); var rows = ExcelUtils.RowsInColumn(worksheet, nameCol); // Insert CV columns after QC(I) and QC(S). CV, Avg CV, Median CV for (var row = startRow; row <= rows + 6; ++row) { var cell = worksheet.Cells[row, nameCol]?.Value?.ToString(); if (cell?.Contains("QC") == true) { // Compare current QC string to next cell QC string var nextCell = worksheet.Cells[row + 1, nameCol]?.Value?.ToString(); if (cell?.Contains("I") == true && nextCell?.Contains("I") == false || cell?.Contains("S") == true && nextCell?.Contains("S") == false || string.IsNullOrWhiteSpace(nextCell)) { // Insert 3 rows worksheet.InsertRow(row + 1, 3); worksheet.Cells[row + 1, nameCol].Value = "CV"; worksheet.Cells[row + 2, nameCol].Value = "Avg CV"; worksheet.Cells[row + 3, nameCol].Value = "Median CV"; /* Guide for row and column names * nameCol nameCol + 1 nameCol + 2 col * startRow QC(I)#1 data startCalc data * QC(I)#2 data | data * row QC(I)#3 data endCalc data * row + 1 CV formula -> copy formula * row + 2 Avg CV * row + 3 Median CV */ // Write first CV formula var startCalc = worksheet.Cells[startRow, nameCol + 1].Address; var endCalc = worksheet.Cells[row, nameCol + 1].Address; worksheet.Cells[row + 1, nameCol + 1].Formula = $"STDEV({startCalc}:{endCalc})/AVERAGE({startCalc}:{endCalc})"; // Copy CV formula across while there is data var col = nameCol + 2; while (!string.IsNullOrWhiteSpace(worksheet.Cells[row, col]?.Value?.ToString())) { worksheet.Cells[row + 1, col - 1].Copy(worksheet.Cells[row + 1, col]); ++col; } // Calculate CV row worksheet.Cells[row + 1, nameCol + 1, row + 1, col - nameCol].Calculate(); // Calculate average and median CV var startCV = worksheet.Cells[row + 1, nameCol + 1].Address; var endCV = worksheet.Cells[row + 1, col - nameCol].Address; worksheet.Cells[row + 2, nameCol + 1] .CreateArrayFormula($"AVERAGE(IF(ISNUMBER({startCV}:{endCV}),{startCV}:{endCV}))"); worksheet.Cells[row + 3, nameCol + 1] .CreateArrayFormula($"MEDIAN(IF(ISNUMBER({startCV}:{endCV}),{startCV}:{endCV}))"); // Format to % with 2 decimal places worksheet.Cells[row + 1, nameCol + 1, row + 3, col - nameCol] .Style.Numberformat.Format = "#0.00%"; // Center and bold text in cell worksheet.Cells[row + 1, nameCol, row + 3, col - nameCol] .Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; worksheet.Cells[row + 1, nameCol, row + 3, col - nameCol].Style.Font.Bold = true; // Reset for next group of QC row += 3; startRow = row + 1; } } else { // Cell was not QC, increment startRow to track the start of CV calculation range ++startRow; } } excelPkg.Save(); //excelPkg.SaveAs(new FileInfo(options["OutputFolder"] + "\\" + options["OutputFileName"])); return(excelPkg); }
// Writes data into Excel tab containing compound and sample names. // Compound names must be in the sheet. Sample names are optional // and will be checked for and filled in if missing. Put sample names in sheet // if you want a particular order. // // The following are optional parameters and can be omitted if using info from options dictionary: // useOptions - default is true. If false, you must fill in the remaining parameters // startRow and startCol - where to start writing data // sampleLoc and compoundLoc - where the sample and compound names are located public static ExcelPackage WriteIntoTemplate( OrderedDictionary dataMap, ExcelPackage excelPkg, Dictionary <string, string> options, string templateTab, bool useOptions = true, int startRow = 2, int startCol = 2, int sampleLoc = 1, int compoundLoc = 1) { var worksheet = excelPkg.Workbook.Worksheets[templateTab]; int numSamples, numCompounds, endRow, endCol; // Check if map contains sample names, prevents index error later List <string> samplesKeys; try { samplesKeys = ((OrderedDictionary)dataMap[0]).Keys.Cast <string>().ToList(); } catch { MessageBox.Show($"No data to write in {templateTab}. " + $"Check if template and samples are in rows or columns."); return(excelPkg); } // Get row and col to start writing if (useOptions) { (startRow, startCol) = ExcelUtils.GetRowCol(options["StartInCell"]); // Convert column name to number sampleLoc = int.TryParse(options["SampleLoc"], out var sampleLocNum) ? sampleLocNum : ExcelUtils.ColumnNameToNumber(options["SampleLoc"]); compoundLoc = int.TryParse(options["CompoundLoc"], out var compoundLocNum) ? compoundLocNum : ExcelUtils.ColumnNameToNumber(options["CompoundLoc"]); } if (options["SamplesOut"] == "rows") { // Fill in sample names if not in template var name = worksheet.Cells[startRow, sampleLoc].Value?.ToString(); if (name is null || name.Length < 1) { var r = startRow; foreach (string sampleName in samplesKeys) { worksheet.Cells[r++, sampleLoc].Value = sampleName; } } // Get approximate bounds, samples in rows (in column sampleLoc) numSamples = ExcelUtils.RowsInColumn(worksheet, sampleLoc); numCompounds = ExcelUtils.ColumnsInRow(worksheet, compoundLoc); endRow = numSamples + startRow; endCol = numCompounds + startCol; // Write each compound data (column) for (int col = startCol; col <= endCol; ++col) { for (int row = startRow; row <= endRow; ++row) { // Write peak area corresponding to compound and sample name // Compound in row compoundLoc var compound = worksheet.Cells[compoundLoc, col]?.Value?.ToString(); if (compound != null && dataMap.Contains(compound)) { // Read sample name from sample column, lookup data for sample in map var sampleName = worksheet.Cells[row, sampleLoc]?.Value?.ToString(); if (sampleName is null) { continue; } var data = ((OrderedDictionary)dataMap[compound])[sampleName]?.ToString(); // Write data to cell, as a number if possible if (double.TryParse(data, out double dataNum)) { worksheet.Cells[row, col].Value = dataNum; } else { worksheet.Cells[row, col].Value = data; } } } } } else { // Fill in sample names if not in template var name = worksheet.Cells[sampleLoc, startCol].Value?.ToString(); if (name is null || name.Length < 1) { var c = startCol; foreach (string sampleName in samplesKeys) { worksheet.Cells[sampleLoc, c++].Value = sampleName; } } // Get approximate bounds, samples in columns (in row sampleLoc) numCompounds = ExcelUtils.RowsInColumn(worksheet, compoundLoc); numSamples = ExcelUtils.ColumnsInRow(worksheet, sampleLoc); endRow = numCompounds + startRow; endCol = numSamples + startCol; // Write each compound data (row) for (int row = startRow; row <= endRow; ++row) { for (int col = startCol; col <= endCol; ++col) { // Write peak area corresponding to compound and sample name // Compounds in column compoundLoc var compound = worksheet.Cells[row, compoundLoc]?.Value?.ToString(); if (compound != null && dataMap.Contains(compound)) { // Read sample name from row, lookup data for sample in map var sampleName = worksheet.Cells[sampleLoc, col]?.Value?.ToString(); if (sampleName is null) { continue; } var data = ((OrderedDictionary)dataMap[compound])[sampleName]?.ToString(); // Write data to cell, as a number if possible if (double.TryParse(data, out double dataNum)) { worksheet.Cells[row, col].Value = dataNum; } else { worksheet.Cells[row, col].Value = data; } } } } } worksheet.Cells[startRow, startCol, endRow, endCol].Style.Numberformat.Format = "0"; worksheet.Cells[startRow, startCol, endRow, endCol].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; // TODO - check that save as new name works //excelPkg.SaveAs(new FileInfo(options["OutputFolder"] + "\\" + options["OutputFileName"])); excelPkg.Save(); return(excelPkg); }