C# - How to copy a single Excel worksheet from one workbook to another?
I have a need to copy a worksheet from one workbook into another and I'm a bit stuck. The premise is that I have a "master" workbook that stores the templates for a number of reports and I then need to create a blank copy of a specific worksheet and add it into a new workbook.
This is what I have so far:
private void CreateNewWorkbook(Tables table)
{
Excel.Application app = null;
Excel.Workbook book = null;
Excel.Worksheet sheet = null;
try
{
string startPath = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
string filePath = System.IO.Path.Combine(startPath, "sal1011forms.xls");
Microsoft.Win32.SaveFileDialog sfd = new Microsoft.Win32.SaveFileDialog();
app = new Excel.Application();
book = app.Workbooks.Open(filePath);
sheet = (Excel.Worksheet)book.Worksheets.get_Item((int)table + 1);
sfd.AddExtension = true;
sfd.FileName = table.ToString() + ".xls";
sfd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
if (sfd.ShowDialog() == true)
{
sheet.SaveAs(sfd.FileName);
}
}
finally
{
if (book != null)
{
book.Close();
}
if (app != null)
{
app.Quit();
}
this.ReleaseObject(sheet);
this.ReleaseObject(book);
this.ReleaseObject(app);
}
}
The only problem I'm having at the moment is that when I call .Save() on the worksheet, it saves ALL of the worksheets from the original workbook into a new workbook. Any ideas on how to correct this?
Thanks in advance,
Sonny
Solution 1:
You could also use the Sheet.Copy()
method.
Basically, Sheet.copy
copies the sheet, and will automatically create a new workbook at the same time.
Try adding the following lines to your code, after your call to Worksheets.get_Item
:
// Copies sheet and puts the copy into a new workbook
sheet.Copy(Type.Missing, Type.Missing);
// Sets the sheet variable to the copied sheet in the new workbook
sheet = app.Workbooks[2].Sheets[1];
Here's the reference for the Copy()
function as well:
MSDN Link
Solution 2:
I realise this is a somewhat late reply, but I struggled quite a bit with this so I figured I'd post my solution so that it might help somebody else having this issue.
Having a template sheet you want to fill many times :
public void test()
{
Excel.Application excelApp;
string fileTarget = "C:\target.xlsx";
string fileTemplate = "C:\template.xlsx";
excelApp = new Excel.Application();
Excel.Workbook wbTemp, wbTarget;
Excel.Worksheet sh;
//Create target workbook
wbTarget = excelApp.Workbooks.Open(fileTemplate);
//Fill target workbook
//Open the template sheet
sh = wbTarget.Worksheets["TEMPLATE"];
//Fill in some data
sh.Cells[1, 1] = "HELLO WORLD!";
//Rename sheet
sh.Name = "1. SHEET";
//Save file
wbTarget.SaveAs(fileTarget);
//Iterate through the rest of the files
for (int i = 1; i < 3; i++)
{
//Open template file in temporary workbook
wbTemp = excelApp.Workbooks.Open(fileTemplate);
//Fill temporary workbook
//Open the template sheet
sh = wbTemp.Worksheets["TEMPLATE"];
//Fill in some data
sh.Cells[1, 1] = "HELLO WORLD! FOR THE " + i + ".TH TIME";
//Rename sheet
sh.Name = i + ". SHEET";
//Copy sheet to target workbook
sh.Copy(wbTarget.Worksheets[1]);
//Close temporary workbook without saving
wbTemp.Close(false);
}
//Close and save target workbook
wbTarget.Close(true);
//Kill excelapp
excelApp.Quit();
}
Solution 3:
I would like to give an answer for this question, even that it's more than a year since it was asked. I had the same problem myself with a project I'm developing, and it took me a while to find the answer. I will post using VB.NET code instead of C# since I'm not familiar with the last.
Here is the deal, in order to copy sheets between Excel workbooks it is absolutely necessary to use only ONE Excel Application object and then open both workbooks with that single application, then we can use the known Worksheet.Copy method and simply specify that the sheet is copied after or before the sheet in that other workbook.
Private Sub ThisWorkbook_Startup() Handles Me.Startup
Me.Application.Workbooks.Open(filePath)
Me.Application.Workbooks(2).Worksheets("Reporte"). _
Copy(After:=Me.Application.Workbooks(1).Worksheets("Hoja1"))
Me.Application.Workbooks(2).Close()
Me.Application.DisplayAlerts = False
Globals.Hoja1.Delete()
Me.Application.DisplayAlerts = True
End Sub
In this case the Excel application I'm using is the one that runs my Excel Workbook project, but this would also work:
Dim xlApp As New Excel.Application
Dim book1 As Excel.Workbook
Dim book2 As Excel.Workbook
book1 = xlApp.Workbooks.Open(filePath1)
book2 = xlApp.Workbooks.Open(filePath2)
book1.Worksheets("Sheet to be copied").Copy(After:=book2.Worksheets(1))
Of course, the Excel Application will show both workbooks, so after you're finished copying you should close the source Workbook if your intention is not to display it (or at least not long enough for the user to do anything).
xlApp.Workbooks(1).Close()
This is the way I could do it, the user will see a blinking new Workbook poping up and then closing, which is not really neat, but so far I have no idea how else to do it (or do this copying process in a not-visible way)
I hope this still has some value. Best regards.