Skip to content

Instantly share code, notes, and snippets.

@sean-m
Last active November 29, 2016 18:56
Show Gist options
  • Save sean-m/c7f813f4490c34cdbfc3 to your computer and use it in GitHub Desktop.
Save sean-m/c7f813f4490c34cdbfc3 to your computer and use it in GitHub Desktop.
Simple command line utility for merging spreadsheets and addings some formatting. There are bugs and some exceptions are not handled gracefully, in my case it does what I need so here's some scissors, start running. Needs Excel 2010+ and .Net 3.5.
using System;
using System.IO;
using System.Linq;
using Microsoft.Office.Interop.Excel;
/* Simple command line utility for merging spreadsheets and
* addings some formatting. There are bugs and some exceptions
* are not handled gracefully, in my case it does what I need
* so here it is.
* -Sean McArdle
*/
namespace JoinSpreadsheet
{
class Program
{
static void Main(string[] args) {
// Check for any arguements
if (args.Length == 0) {
ShowHelp("You must pass a filename");
Environment.Exit(1);
}
// Show full help
if ((args.Contains("-h") ||
args.Contains("--help") ||
args.Contains("/?")) &&
args.Contains("--full")) {
ShowHelp(null, true);
Environment.Exit(0);
}
// Show standard help
if (args.Contains("-h") ||
args.Contains("--help") ||
args.Contains("/?")) {
ShowHelp();
Environment.Exit(0);
}
// Check for arguments
if (args.Length < 2) {
ShowHelp("You must pass a filename");
Environment.Exit(1);
}
// Load workbooks
var excel = new Application();
excel.SheetsInNewWorkbook = 1;
excel.Visible = true;
_Workbook master = (_Workbook)excel.Workbooks.Add();
// Enumerate arguments
int s = 1;
for (int i = 1; i < args.Length; i++) {
string p = args[i];
if (File.Exists(p)) {
WriteDebug("Opening input file: {0}", p);
string path = Path.GetFullPath(p);
var wb = excel.Workbooks.Open(path);
// Enumerate worksheets
foreach (Worksheet ws in wb.Worksheets) {
ws.Application.ActiveWindow.SplitRow = 1;
ws.Application.ActiveWindow.FreezePanes = true;
if (ws.Rows.Count > 0) {
// Freeze first row and apply auto filter
Range fr = (Range)ws.Rows[1];
fr.Activate();
fr.Select();
for (int j = 1; j < fr.Columns.Count; j++) {
try {
fr.AutoFilter(j, Type.Missing, XlAutoFilterOperator.xlAnd, Type.Missing, true);
}
catch {
break;
}
}
Range last = ws.Cells.SpecialCells(XlCellType.xlCellTypeLastCell, Type.Missing);
Range cells = ws.get_Range("A1", last);
cells.Columns.AutoFit();
}
ws.Copy(Type.Missing, master.Sheets[s]);
s++;
}
wb.Close(false, Type.Missing, Type.Missing);
}
else {
var c = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("File: {0} does not exist, check path.", p);
Console.ForegroundColor = c;
}
}
if (excel.Workbooks.Count == 0) {
Console.WriteLine("No workbooks loaded, exiting...");
Environment.Exit(0);
}
else {
((Worksheet)master.Sheets["Sheet1"]).Delete();
// Determine report destination
string name = (Path.IsPathRooted(args[0]))
? String.Format(@"{0}", args[0])
: String.Format(@"{0}\{1}", Environment.CurrentDirectory, args[0]);
WriteDebug("Report name: {0}", name);
// Save report and close excel
string extension = Path.GetExtension(name);
XlFileFormat fmt = XlFileFormat.xlOpenXMLWorkbook;
switch (extension.ToLower()) {
case ".csv":
fmt = XlFileFormat.xlCSVWindows;
break;
case ".ods":
fmt = XlFileFormat.xlOpenDocumentSpreadsheet;
break;
case ".xls":
fmt = XlFileFormat.xlWorkbookNormal;
break;
case ".xml":
fmt = XlFileFormat.xlXMLSpreadsheet;
break;
case ".html":
fmt = XlFileFormat.xlHtml;
break;
default:
// do nothing, stick with OpenXML
break;
}
WriteDebug("File extension: {0} output format: {1}", extension, fmt.ToString());
master.SaveAs(name, fmt);
master.Close();
excel.Workbooks.Close();
excel.Quit();
}
}
private static void ShowHelp(string msg = null, bool full = false) {
if (msg != null) {
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(msg);
Console.WriteLine("\n");
Console.ResetColor();
}
Console.WriteLine("Summary:");
Console.WriteLine(" merge_csv.exe merges worksheets from different spreadsheet");
Console.WriteLine(" formats into a single master workbook.");
Console.WriteLine("");
Console.WriteLine("Command usage: ");
Console.WriteLine(" merge_csv.exe <merged spreadsheet> <input sheet> [additional sheets]");
Console.WriteLine("");
Console.WriteLine(" Argument 0 and 1 are required and may be relative or absolute paths.");
Console.WriteLine("");
Console.WriteLine("Example: ");
Console.WriteLine(" merge_csv.exe master_report.xlsx foo.csv bar.xls baz.csv");
Console.WriteLine("");
Console.WriteLine("Switches:");
Console.WriteLine(" -h, --help, /? : show help");
Console.WriteLine(" Adding --full qualifier shows command symantics.");
Console.WriteLine("");
if (full) {
Console.WriteLine("Symantics:");
Console.WriteLine(" If the merged spreadsheet path is relative and not \"rooted\", path");
Console.WriteLine(" contains a \\ to specify location relative to current, the path is");
Console.WriteLine(" resolved to be the current location of executing shell; not the default");
Console.WriteLine(" excel path (usually Documents) or location of merge_csv.exe.");
}
}
private static void WriteDebug(string msg, params string[] subs) {
#if DEBUG
WriteDebug(String.Format(msg, subs));
#endif
}
private static void WriteDebug(string msg) {
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Debug: {0}", msg);
Console.ResetColor();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment