Intenta interpretar el código bien previamente a usarlo a tu trabajo y si tdeseas aportar algo puedes dejarlo en la sección de comentarios.
Solución:
Si hubiera datos en todas las celdas de una fila, entonces todo funciona bien. En el momento en que tienes una sola celda vacía en una fila, las cosas se vuelven locas.
Por qué está sucediendo en primer lugar?
Esto se debe a que en el siguiente código:
row.Descendants().Count()
|
El Count()
es el numero de no vacio celdas pobladas (no todas las columnas). Entonces, cuando pases row.Descendants
como argumento para GetCellValue
método:
GetCellValue(spreadSheetDocument, row.Descendants().ElementAt(i));
|
Entonces encontrará el contenido de la siguiente no vacio celda poblada (no necesariamente lo que hay en ese índice de columna, i
) por ejemplo, si la primera columna está vacía y llamamos ElementAt(1)
, devuelve el valor en la segunda columna y toda la lógica se estropea.
Solución: tenemos que lidiar con la aparición de celdas vacías: Esencialmente, necesitamos averiguar el índice de columna original de la celda en caso de que hubiera celdas vacías antes. Por lo tanto, debe sustituir su código de bucle for como se muestra a continuación:
for (int i = 0; i < row.Descendants().Count(); i++)
tempRow[i] = GetCellValue(spreadSheetDocument, row.Descendants().ElementAt(i));
| |
con
for (int i = 0; i < row.Descendants().Count(); i++)
Cell cell = row.Descendants().ElementAt(i);
int actualCellIndex = CellReferenceToIndex(cell);
tempRow[actualCellIndex] = GetCellValue(spreadSheetDocument, cell);
| |
y agregue el siguiente método en su código que se usa en el fragmento de código modificado anterior para obtener el índice de columna original / correcto de cualquier celda:
private static int CellReferenceToIndex(Cell cell)
int index = 0;
string reference = cell.CellReference.ToString().ToUpper();
foreach (char ch in reference)
if (Char.IsLetter(ch))
int value = (int)ch - (int)'A';
index = (index == 0) ? value : ((index + 1) * 26) + value;
else
return index;
return index;
public void Read2007Xlsx()
try
DataTable dt = new DataTable();
using (SpreadsheetDocument spreadSheetDocument = SpreadsheetDocument.Open(@"D:File.xlsx", false))
WorkbookPart workbookPart = spreadSheetDocument.WorkbookPart;
IEnumerable sheets = spreadSheetDocument.WorkbookPart.Workbook.GetFirstChild().Elements();
string relationshipId = sheets.First().Id.Value;
WorksheetPart worksheetPart = (WorksheetPart)spreadSheetDocument.WorkbookPart.GetPartById(relationshipId);
Worksheet workSheet = worksheetPart.Worksheet;
SheetData sheetData = workSheet.GetFirstChild();
IEnumerable rows = sheetData.Descendants();
foreach (Cell cell in rows.ElementAt(0))
dt.Columns.Add(GetCellValue(spreadSheetDocument, cell));
foreach (Row row in rows) //this will also include your header row...
DataRow tempRow = dt.NewRow();
int columnIndex = 0;
foreach (Cell cell in row.Descendants())
// Gets the column index of the cell with data
int cellColumnIndex = (int)GetColumnIndexFromName(GetColumnName(cell.CellReference));
cellColumnIndex--; //zero based index
if (columnIndex < cellColumnIndex)
do
tempRow[columnIndex] = ""; //Insert blank data here;
columnIndex++;
while (columnIndex < cellColumnIndex);
tempRow[columnIndex] = GetCellValue(spreadSheetDocument, cell);
columnIndex++;
dt.Rows.Add(tempRow);
dt.Rows.RemoveAt(0); //...so i'm taking it out here.
catch (Exception ex)
///
/// Given a cell name, parses the specified cell to get the column name.
///
/// Address of the cell (ie. B2)
/// Column Name (ie. B)
public static string GetColumnName(string cellReference)
// Create a regular expression to match the column name portion of the cell name.
Regex regex = new Regex("[A-Za-z]+");
Match match = regex.Match(cellReference);
return match.Value;
///
/// Given just the column name (no row index), it will return the zero based column index.
/// Note: This method will only handle columns with a length of up to two (ie. A to Z and AA to ZZ).
/// A length of three can be implemented when needed.
///
/// Column Name (ie. A or AB)
/// Zero based index if the conversion was successful; otherwise null
public static int? GetColumnIndexFromName(string columnName)
//return columnIndex;
string name = columnName;
int number = 0;
int pow = 1;
for (int i = name.Length - 1; i >= 0; i--)
number += (name[i] - 'A' + 1) * pow;
pow *= 26;
return number;
public static string GetCellValue(SpreadsheetDocument document, Cell cell)
SharedStringTablePart stringTablePart = document.WorkbookPart.SharedStringTablePart;
if (cell.CellValue ==null)
return "";
string value = cell.CellValue.InnerXml;
if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString)
return stringTablePart.SharedStringTable.ChildElements[Int32.Parse(value)].InnerText;
else
return value;
|
Acuérdate de que tienes la capacidad de glosar si te fue de ayuda.