Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Open XML SDK 2.0 to get access to excel 2010 worksheet by name

I have an Excel 2010 spreadsheet that has 3 worksheets named Sheet1, Sheet2 and Sheet3.

I'm trying to get a reference to a worksheet by name.

I'm using the code:

using (SpreadsheetDocument myWorkbook = SpreadsheetDocument.Open(FileName, true))
{
    //Access the main Workbook part, which contains all references 
    WorkbookPart workbookPart = myWorkbook.WorkbookPart;

    WorksheetPart worksheetPart = workbookPart.WorksheetParts.Last(); 

    // this gives me Sheet1
    SheetData sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>();
}

I am trying to get a reference to Sheet2, but I cannot find a way to do this.

I'm getting closer, but I'm not there yet:

var x = workbookPart.Workbook.Sheets.Where(s=> s.GetAttribute("name", "").Value == "Sheet2").FirstOrDefault();

That gets me a reference to the sheet, but not to the data on the sheet

Thanks

like image 302
Rick Hodder Avatar asked Jan 11 '12 02:01

Rick Hodder


2 Answers

What you really want is the WorksheetPart which is what contains the SheetData that you are looking for. Grabbing the Sheets under the Workbook will only give you certain metadata about the worksheets. Here is an example on how to grab that WorksheetPart (feel free to add error checking as you see fit as I assume the sheetName already exists by calling First and not FirstOrDefault)

public WorksheetPart GetWorksheetPart(WorkbookPart workbookPart, string sheetName)
{
    string relId = workbookPart.Workbook.Descendants<Sheet>().First(s => sheetName.Equals(s.Name)).Id;
    return (WorksheetPart)workbookPart.GetPartById(relId);
}

Then just use your code above to grab the correct SheetData reference and you will be able to find the data you want from there.

like image 51
amurra Avatar answered Nov 21 '22 00:11

amurra


Here is some code to process a spreadsheet with a specific tab or sheet name and dump it to something like CSV. (I chose a pipe instead of comma).

I wish it was easier to get the value from a cell, but I think this is what we are stuck with. You can see that I reference the MSDN documents where I got most of this code. That is what Microsoft recommends.

    /// <summary>
    /// Got code from: https://msdn.microsoft.com/en-us/library/office/gg575571.aspx
    /// </summary>
    [Test]
    public void WriteOutExcelFile()
    {
        var fileName = "ExcelFiles\\File_With_Many_Tabs.xlsx";
        var sheetName = "Submission Form"; // Existing tab name.
        using (var document = SpreadsheetDocument.Open(fileName, isEditable: false))
        {
            var workbookPart = document.WorkbookPart;
            var sheet = workbookPart.Workbook.Descendants<Sheet>().FirstOrDefault(s => s.Name == sheetName);
            var worksheetPart = (WorksheetPart)(workbookPart.GetPartById(sheet.Id));
            var sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();

            foreach (var row in sheetData.Elements<Row>())
            {
                foreach (var cell in row.Elements<Cell>())
                {
                    Console.Write("|" + GetCellValue(cell, workbookPart));
                }
                Console.Write("\n");
            }
        }
    }

    /// <summary>
    /// Got code from: https://msdn.microsoft.com/en-us/library/office/hh298534.aspx
    /// </summary>
    /// <param name="cell"></param>
    /// <param name="workbookPart"></param>
    /// <returns></returns>
    private string GetCellValue(Cell cell, WorkbookPart workbookPart)
    {
        if (cell == null)
        {
            return null;
        }

        var value = cell.CellFormula != null
            ? cell.CellValue.InnerText 
            : cell.InnerText.Trim();

        // If the cell represents an integer number, you are done. 
        // For dates, this code returns the serialized value that 
        // represents the date. The code handles strings and 
        // Booleans individually. For shared strings, the code 
        // looks up the corresponding value in the shared string 
        // table. For Booleans, the code converts the value into 
        // the words TRUE or FALSE.
        if (cell.DataType == null)
        {
            return value;
        }
        switch (cell.DataType.Value)
        {
            case CellValues.SharedString:

                // For shared strings, look up the value in the
                // shared strings table.
                var stringTable =
                    workbookPart.GetPartsOfType<SharedStringTablePart>()
                        .FirstOrDefault();

                // If the shared string table is missing, something 
                // is wrong. Return the index that is in
                // the cell. Otherwise, look up the correct text in 
                // the table.
                if (stringTable != null)
                {
                    value =
                        stringTable.SharedStringTable
                            .ElementAt(int.Parse(value)).InnerText;
                }
                break;

            case CellValues.Boolean:
                switch (value)
                {
                    case "0":
                        value = "FALSE";
                        break;
                    default:
                        value = "TRUE";
                        break;
                }
                break;
        }
        return value;
    }
like image 38
Jess Avatar answered Nov 20 '22 23:11

Jess