Using OpenXmlReader

I think you took the wrong WorksheetPart for reading the rows.

The line

workbookPart.WorksheetParts.First();

gets the first WorksheetPart of the collection which must not
necessarily be the first worksheet as you see it in Microsoft Excel.

So, iterate through all WorksheetParts and you should see some output on your
console window.

static void ReadExcelFileSAX(string fileName)
{
  using (SpreadsheetDocument spreadsheetDocument = 
                                   SpreadsheetDocument.Open(fileName, true))
  {
    WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;

    // Iterate through all WorksheetParts
    foreach (WorksheetPart worksheetPart in workbookPart.WorksheetParts)
    {          
      OpenXmlPartReader reader = new OpenXmlPartReader(worksheetPart);
      string text;
      string rowNum;
      while (reader.Read())
      {
        if (reader.ElementType == typeof(Row))
        {
          do
          {
            if (reader.HasAttributes)
            {
              rowNum = reader.Attributes.First(a => a.LocalName == "r").Value;
              Console.Write("rowNum: " + rowNum);
            }

          } while (reader.ReadNextSibling()); // Skip to the next row

          break; // We just looped through all the rows so no 
                 // need to continue reading the worksheet
        }

        if (reader.ElementType != typeof(Worksheet))
          reader.Skip(); 
      }
      reader.Close();      
    }
  }  
}

To read all cell values use the following function (all error handling details omitted) :

static void ReadAllCellValues(string fileName)
{
  using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(fileName, false))
  {
    WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;

    foreach(WorksheetPart worksheetPart in workbookPart.WorksheetParts)
    {
      OpenXmlReader reader = OpenXmlReader.Create(worksheetPart);

      while (reader.Read())
      {
        if (reader.ElementType == typeof(Row))
        {
          reader.ReadFirstChild();

          do
          {
            if (reader.ElementType == typeof(Cell))
            {
              Cell c = (Cell)reader.LoadCurrentElement();

              string cellValue;

              if (c.DataType != null && c.DataType == CellValues.SharedString)
              {
                SharedStringItem ssi = workbookPart.SharedStringTablePart.SharedStringTable.Elements<SharedStringItem>().ElementAt(int.Parse(c.CellValue.InnerText));

                cellValue = ssi.Text.Text;
              }
              else
              {
                cellValue = c.CellValue.InnerText;
              }

              Console.Out.Write("{0}: {1} ", c.CellReference, cellValue);
            }
          } while (reader.ReadNextSibling());
          Console.Out.WriteLine();
        }            
      }
    }   
  }
}

In the code above you see that cells with data type SharedString must be handled using
the SharedStringTablePart.

Leave a Comment