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.