Solutions to Merge Multiple Excel Worksheets Into One

Introduction

In the daily routine, Excel is indispensable for us to processing data. We usually need to merge multiple worksheets or workbooks into one when use Excel, so that we can analyze and count the data quickly and conveniently. Generally, we use copy and paste command to achieve the goal for most people. It’s a good solution if you just have a small number of Excel files or worksheets, but if there are numerous worksheets, this method will be excruciating and time-consuming. Thus, this article aims at talking about some useful solutions for you to solve this problem.

Background

In fact, I have some large Excel files that have the same construction, and I need to merge them into one worksheet so that I could extract one of the columns and export it into another Excel file or worksheet. They have 7 columns and more than 1000 rows, I know I cannot complete the process by hand with copy and paste command. So I need certain easier method to help me. Luckily, I collected some useful and verified solutions through Google and I am very willing to share them with you here.

How Many Kinds of Solutions

I have verified 4 solutions so far. One of them is to merge the worksheets through a small tool, and the rest are using C# code to achieve the implementation. Of course, most of them are free methods, which are easily found on the Internet. For the sake of the security, I will not use my own worksheet but the sample sheet in the solutions below. The two sample sheets have 5 columns and 10 rows (not including the first row). What we need do is to merge the two worksheets into one. I hope these solutions are also useful for you guys.

Solution1: using Microsoft.Office.Interop.Excel;

Although the method is free, you must install Microsoft Office on your machine, so that you could run the code successfully. If you have installed the Microsoft Office on your machine, it’s a good choice for you. Besides, the code is a little complicated. Anyway, it could help achieve my goal. Please refer the code below:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Reflection;  
  6. using Microsoft.Office.Interop.Excel;  
  7. using System.IO;  
  8. using Excel = Microsoft.Office.Interop.Excel;  
  9.   
  10. namespace ConsoleApplication3  
  11. {  
  12.     class Program  
  13.     {  
  14.         static void Main(string[] args)  
  15.         {  
  16.             MergeExcel.DoMerge(new string[]   
  17.             {  
  18.                 @"D:\Test Files\ConsoleApplication3\ConsoleApplication3\merge1.xlsx",   
  19.                 @"D:\Test Files\ConsoleApplication3\ConsoleApplication3\merge2.xlsx"   
  20.             },  
  21.                 @"D:\Test Files\ConsoleApplication3\ConsoleApplication3\result.xlsx""E", 2);  
  22.         }  
  23.     }  
  24.     public class MergeExcel  
  25.     {  
  26.         Excel.Application app = new Microsoft.Office.Interop.Excel.ApplicationClass();  
  27.         Excel.Workbook bookDest = null;  
  28.         Excel.Worksheet sheetDest = null;   
  29.         Excel.Workbook bookSource = null;  
  30.         Excel.Worksheet sheetSource = null;  
  31.         string[] _sourceFiles = null;  
  32.         string _destFile = string.Empty;  
  33.         string _columnEnd = string.Empty;  
  34.         int _headerRowCount = 0;  
  35.         int _currentRowCount = 0;  
  36.         public MergeExcel(string[] sourceFiles, string destFile, string columnEnd, int headerRowCount)  
  37.         {  
  38.             bookDest = (Excel.WorkbookClass)app.Workbooks.Add(Missing.Value);  
  39.             sheetDest = bookDest.Worksheets.Add(Missing.Value, Missing.Value, Missing.Value, Missing.Value) as Excel.Worksheet;  
  40.             sheetDest.Name = "Data";  
  41.             _sourceFiles = sourceFiles;  
  42.             _destFile = destFile;  
  43.             _columnEnd = columnEnd;  
  44.             _headerRowCount = headerRowCount;  
  45.         }  
  46.         void OpenBook(string fileName)  
  47.         {  
  48.             bookSource = app.Workbooks._Open(fileName, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value);  
  49.             sheetSource = bookSource.Worksheets[1] as Excel.Worksheet;  
  50.         }  
  51.         void CloseBook()  
  52.         {  
  53.             bookSource.Close(false, Missing.Value, Missing.Value);  
  54.         }  
  55.   
  56.         void CopyHeader()  
  57.         {  
  58.             Excel.Range range = sheetSource.get_Range("A1", _columnEnd + _headerRowCount.ToString());  
  59.             range.Copy(sheetDest.get_Range("A1", Missing.Value));  
  60.             _currentRowCount += _headerRowCount;  
  61.         }  
  62.         void CopyData()  
  63.         {  
  64.             int sheetRowCount = sheetSource.UsedRange.Rows.Count;  
  65.             Excel.Range range = sheetSource.get_Range(string.Format("A{0}", _headerRowCount), _columnEnd + sheetRowCount.ToString());  
  66.             range.Copy(sheetDest.get_Range(string.Format("A{0}", _currentRowCount), Missing.Value));  
  67.             _currentRowCount += range.Rows.Count;  
  68.         }  
  69.         void Save()  
  70.         {  
  71.             bookDest.Saved = true;  
  72.             bookDest.SaveCopyAs(_destFile);  
  73.         }  
  74.         void Quit()  
  75.         {  
  76.             app.Quit();  
  77.         }  
  78.         void DoMerge()  
  79.         {  
  80.             bool b = false;  
  81.             foreach (string strFile in _sourceFiles)  
  82.             {  
  83.                 OpenBook(strFile);  
  84.                 if (b == false)  
  85.                 {  
  86.                     CopyHeader();  
  87.                     b = true;  
  88.                 }  
  89.                 CopyData();  
  90.                 CloseBook();  
  91.             }  
  92.             Save();  
  93.             Quit();  
  94.         }  
  95.         public static void DoMerge(string[] sourceFiles, string destFile, string columnEnd, int headerRowCount)  
  96.         {  
  97.             new MergeExcel(sourceFiles, destFile, columnEnd, headerRowCount).DoMerge();  
  98.         }  
  99.     }  
  100. }  

Note: please set the reference property as false.

 

Here comes to the effect screenshot:

 

Solution2: using NPOI.XSSF.UserModel; using NPOI.HSSF.UserModel;


The second method is to use the third party component NPOI. What I used is the free version. The advantage of NPOI is that it doesn't need Microsoft Office to be installed on the machine. The code is also a little complicated. Download it from here. Please refer the code below:
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.IO;  
  6. using NPOI.XSSF.UserModel;  
  7. using System.Data;  
  8. using NPOI.HSSF.UserModel;  
  9.   
  10. namespace method2  
  11. {  
  12.     class Program  
  13.     {  
  14.         static void Main(string[] args)  
  15.         {  
  16.             DataTable dt = new DataTable();  
  17.             string[] files = new string[] { @"..\..\merge1.xlsx", @"..\..\merge2.xlsx"};  
  18.             for (int i = 0; i < files.Length; i++)  
  19.             {  
  20.                 MergeData(files[i], dt);  
  21.             }  
  22.             ExportEasy(dt, @"..\..\result.xls");  
  23.         }  
  24.         private static void MergeData(string path, DataTable dt)  
  25.         {  
  26.             XSSFWorkbook workbook = new XSSFWorkbook(path);  
  27.             XSSFSheet sheet = (XSSFSheet)workbook.GetSheetAt(0);  
  28.             XSSFRow headerRow = (XSSFRow)sheet.GetRow(0);  
  29.             int cellCount = headerRow.LastCellNum;  
  30.             if (dt.Rows.Count == 0)  
  31.             {  
  32.                for (int i = headerRow.FirstCellNum; i < cellCount; i++)  
  33.                 {  
  34.                     DataColumn column = new DataColumn(headerRow.GetCell(i).StringCellValue);  
  35.                     dt.Columns.Add(column);  
  36.                 }  
  37.             }  
  38.             else  
  39.             {  
  40.              }  
  41.   
  42.             int rowCount = sheet.LastRowNum + 1;  
  43.             for (int i = (sheet.FirstRowNum + 1); i < rowCount; i++)  
  44.             {  
  45.                 XSSFRow row = (XSSFRow)sheet.GetRow(i);  
  46.                 DataRow dataRow = dt.NewRow();  
  47.                 for (int j = row.FirstCellNum; j < cellCount; j++)  
  48.                 {  
  49.                     if (row.GetCell(j) != null)  
  50.                         dataRow[j] = row.GetCell(j).ToString();  
  51.                 }  
  52.                 dt.Rows.Add(dataRow);  
  53.             }  
  54.             workbook = null;  
  55.             sheet = null;  
  56.         }  
  57.         public static void ExportEasy(DataTable dtSource, string strFileName)  
  58.         {  
  59.             HSSFWorkbook workbook = new HSSFWorkbook();  
  60.             HSSFSheet sheet = (HSSFSheet)workbook.CreateSheet();  
  61.             HSSFRow dataRow = (HSSFRow)sheet.CreateRow(0);  
  62.             foreach (DataColumn column in dtSource.Columns)  
  63.             {  
  64.                 dataRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName);  
  65.             }  
  66. for (int i = 0; i < dtSource.Rows.Count; i++)  
  67.             {  
  68.                 dataRow = (HSSFRow)sheet.CreateRow(i + 1);  
  69.                 for (int j = 0; j < dtSource.Columns.Count; j++)  
  70.                 {  
  71.                     dataRow.CreateCell(j).SetCellValue(dtSource.Rows[i][j].ToString());  
  72.                 }  
  73.             }  
  74. using (MemoryStream ms = new MemoryStream())  
  75.             {  
  76.                 using (FileStream fs = new FileStream(strFileName, FileMode.Create, FileAccess.Write))  
  77.                 {  
  78.                     workbook.Write(fs);  
  79.                 }  
  80.             }  
  81.         }  
  82.     }  
  83. }  

Note: as NPOI could not support the .xlsx document, please set the generated file as the .xls document. What below is the effect screenshot:

 
 
Solution3: using org.in2bits.MyXls;

The method is similar with the second method. It also completes the process with the help of a third party component called MyXls. It is an open source software that will let you perform Data Formats and Spreadsheet tasks. Also it doesn't require Excel on the machine or any licensing, but the flaw is that the first row of the second worksheet could not be removed. Download it from here. Please refer the code below:
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4. using org.in2bits.MyXls;  
  5. using System.Data;  
  6. using System.IO;  
  7. using System.ComponentModel;  
  8. using System.Reflection;  
  9.   
  10. namespace method3_MyXls_  
  11. {  
  12.     class Program  
  13.     {  
  14.         static void Main(string[] args)  
  15.         {  
  16.             XlsDocument xls = null;  
  17.             DataTable dt = new DataTable();  
  18.             List<string[]> list = new List<string[]>();  
  19.             String[] str = null;  
  20.             string[] xlsfiles = new string[] { @"..\..\merge1.xls", @"..\..\merge2.xls" };  
  21.             for (int i = 0; i < xlsfiles.Length; i++)  
  22.             {  
  23.                 xls = new XlsDocument(xlsfiles[i]);  
  24.                 Worksheet sheet = xls.Workbook.Worksheets[0];  
  25.                 for (int j = 1; j < sheet.Rows.Count; j++)  
  26.                 {  
  27.                     str = new string[sheet.Rows[ushort.Parse(j.ToString())].CellCount];  
  28.                     for (int z = 1; z < sheet.Rows[ushort.Parse(j.ToString())].CellCount + 1; z++)  
  29.                     {  
  30.                         str[z - 1] = Convert.ToString(sheet.Rows[ushort.Parse(j.ToString())].GetCell(ushort.Parse(z.ToString())).Value);  
  31.                     }  
  32.                     list.Add(str);  
  33.                 }  
  34.             }  
  35.             dt = ConvertListToDataTable(list);  
  36.             ExportToExcel(dt, "result.xls");  
  37.         }  
  38.         static DataTable ConvertListToDataTable(List<string[]> list)  
  39.         {  
  40.             DataTable table = new DataTable();  
  41. int columns = 0;  
  42.             foreach (var array in list)  
  43.             {  
  44.                 if (array.Length > columns)  
  45.                 {  
  46.                     columns = array.Length;  
  47.                 }  
  48.             }  
  49.             for (int i = 0; i < columns; i++)  
  50.             {  
  51.                 table.Columns.Add();  
  52.             }  
  53.             foreach (var array in list)  
  54.             {  
  55.                 table.Rows.Add(array);  
  56.             }  
  57.             return table;  
  58.         }  
  59.         public static void ExportToExcel(DataTable dtSource, string strFileName)  
  60.         {  
  61.             XlsDocument xls = new XlsDocument();  
  62.             Worksheet sheet = xls.Workbook.Worksheets.Add("sheet1");  
  63.             for (int i = 0; i < dtSource.Rows.Count; i++)  
  64.             {  
  65.                 for (int j = 0; j < dtSource.Columns.Count; j++)  
  66.                 {  
  67.                     sheet.Cells.Add(i + 1, j + 1, dtSource.Rows[i][j].ToString());  
  68.                 }  
  69.             }  
  70.             xls.FileName = strFileName;  
  71.             if (File.Exists(strFileName))  
  72.             {  
  73.                 File.Delete(strFileName);  
  74.             }  
  75.             xls.Save();  
  76.         }  
  77.     }  
  78. }  
 Note: as the second solution, you need to set the generated file as .xls document as well. Here is the effect screenshot.
 
 

Solution4: using Spire.Xls
;

This method is the simplest way to merge worksheets into one among these 4 solutions through a third part component called Spire.Xls. It’s a standalone .NET component that dispenses with Microsoft Office installed on the machine as well. Download it from here. Please refer the code below:
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using Spire.Xls;  
  6. using System.Data;  
  7.   
  8. namespace Spire.XLS  
  9. {  
  10.     class Program  
  11.     {  
  12.         static void Main(string[] args)  
  13.         {  
  14.             Workbook workbook = new Workbook();  
  15.             workbook.LoadFromFile(@"merge1.xlsx");  
  16.             Workbook workbook2 = new Workbook();  
  17.             workbook2.LoadFromFile(@"merge2.xlsx");  
  18.             Worksheet sheet2 = workbook2.Worksheets[0];  
  19.             DataTable dataTable = sheet2.ExportDataTable();  
  20.             Worksheet sheet1 = workbook.Worksheets[0];  
  21.             sheet1.InsertDataTable(dataTable, false, sheet1.LastRow + 1, 1);  
  22. workbook.SaveToFile("result.xlsx");  
  23.         }  
  24.     }  
  25. }  

Note: Spire.Xls is not a free component, an evaluation warning will be generated in a new worksheet, but it’s unaffected to the result. Here comes to the perfect effect screenshot:

 

Conclusion


Please kindly note that all of the components and software are run on the system Windows 7 32 bit. I just installed the Windows 8 theme so that my windows 7 system looks great like the windows 8. Besides, I didn’t spend even 1 dollar on these solutions. You should be on the basis of your own specific circumstance to choose the right solution. Hope these solutions could help you. I think I will continue to share my experience here.