user3659569
user3659569

Reputation: 31

Openxml cell returns InnerText not the actual value

Im developing a reusable code to read the excel cell value. My code as follows:

private string ReadCellValue(WorksheetPart worksheetPart, string cellAddress)
        {
            string value = null;

            Cell theCell = worksheetPart.Worksheet.Descendants<Cell>().
                  Where(c => c.CellReference == cellAddress).FirstOrDefault();

            // If the cell does not exist, return an empty string.
            if (theCell != null)
            {
                value = theCell.InnerText;

                if (theCell.DataType != null)
                {
                    switch (theCell.DataType.Value)
                    {
                        case CellValues.SharedString:

                            var stringTable =
                                worksheetPart.GetPartsOfType<SharedStringTablePart>()
                                .FirstOrDefault();

                            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;
        }

Im calling this method from following code block:

public string IsPackingListValid()
        {           

            // Open the spreadsheet document for read-only access.
            using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, false))
            {
                // Retrieve a reference to the workbook part.
                WorkbookPart wbPart = document.WorkbookPart;

                // Find the sheet with the supplied name, and then use that 
                // Sheet object to retrieve a reference to the first worksheet.
                Sheet theSheet = wbPart.Workbook.Descendants<Sheet>().
                  Where(s => s.Name == sheetName).FirstOrDefault();

                // Throw an exception if there is no sheet.
                if (theSheet == null)
                {
                    throw new ArgumentException("Could not find work sheet: " + sheetName);
                }

                // Retrieve a reference to the worksheet part.
                WorksheetPart worksheetPart = (WorksheetPart)(wbPart.GetPartById(theSheet.Id));

                return ReadCellValue(WorksheetPart worksheetPart, "B2")
            }   
}

The method does not return the actual value for some cells. For some cells it returns the value and for some cells it returns the inner text. I debuged and checked

var stringTable = worksheetPart.GetPartsOfType<SharedStringTablePart>()
                               .FirstOrDefault();

the above code returns null.

I cant find why it s working for some cells and not working for some. Any helps to resolve this.

Upvotes: 2

Views: 4486

Answers (2)

user500099
user500099

Reputation: 973

Also an extra check on SharedString datatype is needed (http://msdn.microsoft.com/en-us/library/office/ff921204(v=office.14).aspx for more info):

    private static string ReadCellValue(WorksheetPart worksheetPart, string cellAddress, List<SharedStringItem> sharedStrings)
    {
        try
        {
            string value = null;
            var cell = worksheetPart.Worksheet.Descendants<Cell>().Where(c => c.CellReference == cellAddress).FirstOrDefault();
            value = cell.InnerText;
            if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString)
            {
                int sharedStringIndex;
                if (int.TryParse(cell.InnerText, out sharedStringIndex) && sharedStrings.Count > sharedStringIndex && sharedStrings[sharedStringIndex].Text != null)
                {
                    value = sharedStrings[sharedStringIndex].Text.Text;
                }
            }
            return value;
        }
        catch (Exception ex) { throw ex; }
    }

Upvotes: 0

Siarhei Tyshkavets
Siarhei Tyshkavets

Reputation: 392

From my understanding (at least, it's true for a document I've checked it on), SharedStringTablePart is a descendant of WorkbookPart rather than WorksheetPart. So what you can do to fix your code is to get a list of shared strings from wbPart in IsPackingListValid() method:

List<SharedStringItem> sharedStrings = wbPart.SharedStringTablePart.SharedStringTable.ChildElements.OfType<SharedStringItem>().ToList();

And then pass it into ReadCellValue method as an additional argument:

return ReadCellValue(worksheetPart, "B2", sharedStrings);

After it, you can get actual value of your Shared string inside of your switch in ReadCellValue() method:

value = cell.InnerText;
int sharedStringIndex;

if (int.TryParse(cell.InnerText, out sharedStringIndex) && sharedStrings.Count > sharedStringIndex
    && sharedStrings[sharedStringIndex].Text != null)
{
    value = sharedStrings[sharedStringIndex].Text.Text;
}

Upvotes: 6

Related Questions