I discovered that using OpenXml my columns don't always line up. For instance look at this example
This is the header row column 37 = "Exchange Only" column 38 = "Qty On Hand" column 39 = "Cost Method" column 40 = "Cost Method Amount"
Now, in the next row - the one that has actual data in both 37 and 38 are blank but it omits column 38. so my data looks like this.
column 37 = "" (should be blank) column 38 = "Set Amount" (Should be blank cause it should line up with 'Qty On Hand') column 39 = 0
Notice that it dropped out the real column / cell 38 and now my parser no longer lines up. both 37 and 38 are blank but it doesn't lose 37.
Here is some code to show how I am getting to the string array - it's really just a modified example from MSDN.
public InventoryItemLoadProxy CreateInventoryItemFromSpreadsheetRow(Row row, SharedStringTable sharedStrings)
     {
         var invItem = new InventoryItemLoadProxy();
         var theCells = row.Descendants<Cell>();
         var textValues =
             from cell in row.Descendants<Cell>()
             select(cell.CellValue == null ? string.Empty : ((cell.DataType != null
                             && cell.DataType.HasValue
                              && cell.DataType == CellValues.SharedString) ? sharedStrings.ChildElements[int.Parse(cell.CellValue.InnerText)].InnerText : cell.CellValue.InnerText));
          if(textValues.Any(x => x != string.Empty))
          {
             var textArray = textValues.ToArray();
             invItem.PartNumber = textArray[0].ToStrippedPartNumber();
             invItem.DisplayPartNumber = textArray[0];
             //More parsing...
         }
    }
You can see I am saying if it's null just make it string.empty (yeah - that crazy linq statement will get refactored at some point).
 
     
    