C# 使用OpenXMLSDK读取excel文件时遇到问题
我有一个函数,可以从excel文件中读取数据,并将结果存储在C# 使用OpenXMLSDK读取excel文件时遇到问题,c#,asp.net,excel,openxml,openxml-sdk,C#,Asp.net,Excel,Openxml,Openxml Sdk,我有一个函数,可以从excel文件中读取数据,并将结果存储在数据集中。我有另一个函数,可以写入excel文件。当我尝试从常规的人工生成的excel文件中读取时,excel reading函数返回一个空白的数据集,但当我从writing函数生成的excel文件中读取时,它工作得非常好。然后,即使我只是复制并粘贴函数生成的excel文件的内容,该函数也不会在常规生成的excel文件上工作。我终于找到了答案,但我不知道该怎么办。我的代码有问题吗 以下是excel生成函数: public static
数据集中。我有另一个函数,可以写入excel文件。当我尝试从常规的人工生成的excel文件中读取时,excel reading函数返回一个空白的数据集
,但当我从writing函数生成的excel文件中读取时,它工作得非常好。然后,即使我只是复制并粘贴函数生成的excel文件的内容,该函数也不会在常规生成的excel文件上工作。我终于找到了答案,但我不知道该怎么办。我的代码有问题吗
以下是excel生成函数:
public static Boolean writeToExcel(string fileName, DataSet data)
{
Boolean answer = false;
using (SpreadsheetDocument excelDoc = SpreadsheetDocument.Create(tempPath + fileName, SpreadsheetDocumentType.Workbook))
{
WorkbookPart workbookPart = excelDoc.AddWorkbookPart();
workbookPart.Workbook = new Workbook();
WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
Sheets sheets = excelDoc.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets());
Sheet sheet = new Sheet()
{
Id = excelDoc.WorkbookPart.GetIdOfPart(worksheetPart),
SheetId = 1,
Name = "Page1"
};
sheets.Append(sheet);
CreateWorkSheet(worksheetPart, data);
answer = true;
}
return answer;
}
private static void CreateWorkSheet(WorksheetPart worksheetPart, DataSet data)
{
Worksheet worksheet = new Worksheet();
SheetData sheetData = new SheetData();
UInt32Value currRowIndex = 1U;
int colIndex = 0;
Row excelRow;
DataTable table = data.Tables[0];
for (int rowIndex = -1; rowIndex < table.Rows.Count; rowIndex++)
{
excelRow = new Row();
excelRow.RowIndex = currRowIndex++;
for (colIndex = 0; colIndex < table.Columns.Count; colIndex++)
{
Cell cell = new Cell()
{
CellReference = Convert.ToString(Convert.ToChar(65 + colIndex)),
DataType = CellValues.String
};
CellValue cellValue = new CellValue();
if (rowIndex == -1)
{
cellValue.Text = table.Columns[colIndex].ColumnName.ToString();
}
else
{
cellValue.Text = (table.Rows[rowIndex].ItemArray[colIndex].ToString() != "") ? table.Rows[rowIndex].ItemArray[colIndex].ToString() : "*";
}
cell.Append(cellValue);
excelRow.Append(cell);
}
sheetData.Append(excelRow);
}
SheetFormatProperties formattingProps = new SheetFormatProperties()
{
DefaultColumnWidth = 20D,
DefaultRowHeight = 20D
};
worksheet.Append(formattingProps);
worksheet.Append(sheetData);
worksheetPart.Worksheet = worksheet;
}
公共静态布尔writeToExcel(字符串文件名、数据集数据)
{
布尔答案=假;
使用(SpreadsheetDocument excelDoc=SpreadsheetDocument.Create(临时路径+文件名,SpreadsheetDocumentType.工作簿))
{
WorkbookPart WorkbookPart=excelDoc.AddWorkbookPart();
workbookPart.工作簿=新工作簿();
WorksheetPart WorksheetPart=workbookPart.AddNewPart();
Sheets Sheets=excelDoc.WorkbookPart.Workbook.AppendChild(新工作表());
图纸=新图纸()
{
Id=excelDoc.WorkbookPart.GetIdOfPart(工作表部分),
SheetId=1,
Name=“第1页”
};
附页(页);
创建工作表(工作表部分、数据);
答案=正确;
}
返回答案;
}
专用静态void CreateSheet(工作表部件工作表部件,数据集数据)
{
工作表=新工作表();
SheetData SheetData=新的SheetData();
UINT32值currowIndex=1U;
int-colIndex=0;
行,行;
DataTable=数据表[0];
for(int-rowIndex=-1;rowIndex
而读取功能如下所示:
public static void readInventoryExcel(string fileName, ref DataSet set)
{
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(fileName, false))
{
WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();
int count = -1;
foreach (Row r in sheetData.Elements<Row>())
{
if (count >= 0)
{
DataRow row = set.Tables[0].NewRow();
row["SerialNumber"] = r.ChildElements[1].InnerXml;
row["PartNumber"] = r.ChildElements[2].InnerXml;
row["EntryDate"] = r.ChildElements[3].InnerXml;
row["RetirementDate"] = r.ChildElements[4].InnerXml;
row["ReasonForReplacement"] = r.ChildElements[5].InnerXml;
row["RetirementTech"] = r.ChildElements[6].InnerXml;
row["IncludeInMaintenance"] = r.ChildElements[7].InnerXml;
row["MaintenanceTech"] = r.ChildElements[8].InnerXml;
row["Comment"] = r.ChildElements[9].InnerXml;
row["Station"] = r.ChildElements[10].InnerXml;
row["LocationStatus"] = r.ChildElements[11].InnerXml;
row["AssetName"] = r.ChildElements[12].InnerXml;
row["InventoryType"] = r.ChildElements[13].InnerXml;
row["Description"] = r.ChildElements[14].InnerXml;
set.Tables[0].Rows.Add(row);
}
count++;
}
}
}
publicstaticvoid readInventoryExcel(字符串文件名,ref数据集集)
{
使用(SpreadsheetDocument SpreadsheetDocument=SpreadsheetDocument.Open(文件名,false))
{
WorkbookPart WorkbookPart=电子表格文档.WorkbookPart;
WorksheetPart WorksheetPart=workbookPart.WorksheetParts.First();
SheetData SheetData=worksheetPart.Worksheet.Elements().First();
整数计数=-1;
foreach(sheetData.Elements()中的r行)
{
如果(计数>=0)
{
DataRow row=set.Tables[0].NewRow();
行[“SerialNumber”]=r.ChildElements[1]。InnerXml;
行[“PartNumber”]=r.ChildElements[2].InnerXml;
行[“EntryDate”]=r.ChildElements[3].InnerXml;
行[“RetirementDate”]=r.ChildElements[4].InnerXml;
行[“ReasonForReplacement”]=r.ChildElements[5].InnerXml;
行[“RetirementTech”]=r.ChildElements[6].InnerXml;
行[“IncludeInMaintenance”]=r.ChildElements[7].InnerXml;
行[“MaintenanceTech”]=r.ChildElements[8].InnerXml;
行[“Comment”]=r.ChildElements[9].InnerXml;
行[“Station”]=r.ChildElements[10].InnerXml;
行[“LocationStatus”]=r.ChildElements[11].InnerXml;
行[“AssetName”]=r.ChildElements[12].InnerXml;
行[“InventoryType”]=r.ChildElements[13].InnerXml;
行[“Description”]=r.ChildElements[14].InnerXml;
set.Tables[0].Rows.Add(row);
}
计数++;
}
}
}
我在前一段时间尝试对Word文档执行此操作时遇到了类似的问题(程序生成的效果很好,但人工生成的效果不好)。我发现这个工具非常有用:
基本上,它会查看一个文件,并向您显示Microsoft为读取该文件而生成的代码,以及文件本身的xml结构。和往常一样,微软的产品有很多菜单,而且不是很直观,但是在点击一下之后,你将能够准确地看到任意两个文件的运行情况。我建议您打开一个工作excel文件和一个非工作excel文件,比较两者之间的差异,看看是什么导致了您的问题。我认为这是因为您只有一张工作表,而excel有三张工作表。我不确定,但我认为这些表是按相反的顺序返回的,因此您应该更改行:
WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
CellReference = Convert.ToString(Convert.ToChar(65 + colIndex)),
到
如果可以通过工作表名称识别工作表部件,则搜索工作表部件可能更安全。您需要先找到图纸
,然后使用该图纸的Id来查找图纸零件
:
private WorksheetPart GetWorksheetPartBySheetName(WorkbookPart workbookPart, string sheetName)
{
//find the sheet first.
IEnumerable<Sheet> sheets = workbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>().Where(s => s.Name == sheetName);
if (sheets.Count() > 0)
{
string relationshipId = sheets.First().Id.Value;
WorksheetPart worksheetPart = (WorksheetPart)workbookPart.GetPartById(relationshipId);
return worksheetPart;
}
return null;
}
在查看您的代码时,我还注意到了一些其他的事情,它们是y
WorksheetPart worksheetPart = GetWorksheetPartBySheetName(workbookPart, "Sheet1");
var stringTable = workbookPart.GetPartsOfType<SharedStringTablePart>().FirstOrDefault();
if (stringTable != null)
{
sharedString = stringTable.SharedStringTable.ElementAt(int.Parse(value)).InnerText;
}
CellReference = Convert.ToString(Convert.ToChar(65 + colIndex)),
CellReference = Convert.ToString(Convert.ToChar(65 + colIndex) + rowIndex.ToString()),
DataTable dt = OpenXMLHelper.ExcelWorksheetToDataTable("C:\\SQL Server\\SomeExcelFile.xlsx", "Mikes Worksheet");
public class OpenXMLHelper
{
public static DataTable ExcelWorksheetToDataTable(string pathFilename, string worksheetName)
{
DataTable dt = new DataTable(worksheetName);
using (SpreadsheetDocument document = SpreadsheetDocument.Open(pathFilename, false))
{
// Find the sheet with the supplied name, and then use that
// Sheet object to retrieve a reference to the first worksheet.
Sheet theSheet = document.WorkbookPart.Workbook.Descendants<Sheet>().Where(s => s.Name == worksheetName).FirstOrDefault();
if (theSheet == null)
throw new Exception("Couldn't find the worksheet: " + worksheetName);
// Retrieve a reference to the worksheet part.
WorksheetPart wsPart = (WorksheetPart)(document.WorkbookPart.GetPartById(theSheet.Id));
Worksheet workSheet = wsPart.Worksheet;
string dimensions = workSheet.SheetDimension.Reference.InnerText; // Get the dimensions of this worksheet, eg "B2:F4"
int numOfColumns = 0;
int numOfRows = 0;
CalculateDataTableSize(dimensions, ref numOfColumns, ref numOfRows);
System.Diagnostics.Trace.WriteLine(string.Format("The worksheet \"{0}\" has dimensions \"{1}\", so we need a DataTable of size {2}x{3}.", worksheetName, dimensions, numOfColumns, numOfRows));
SheetData sheetData = workSheet.GetFirstChild<SheetData>();
IEnumerable<Row> rows = sheetData.Descendants<Row>();
string[,] cellValues = new string[numOfColumns, numOfRows];
int colInx = 0;
int rowInx = 0;
string value = "";
SharedStringTablePart stringTablePart = document.WorkbookPart.SharedStringTablePart;
// Iterate through each row of OpenXML data
foreach (Row row in rows)
{
for (int i = 0; i < row.Descendants<Cell>().Count(); i++)
{
// *DON'T* assume there's going to be one XML element for each item in each row...
Cell cell = row.Descendants<Cell>().ElementAt(i);
if (cell.CellValue == null || cell.CellReference == null)
continue; // eg when an Excel cell contains a blank string
// Convert this Excel cell's CellAddress into a 0-based offset into our array (eg "G13" -> [6, 12])
colInx = GetColumnIndexByName(cell.CellReference); // eg "C" -> 2 (0-based)
rowInx = GetRowIndexFromCellAddress(cell.CellReference)-1; // Needs to be 0-based
// Fetch the value in this cell
value = cell.CellValue.InnerXml;
if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString)
{
value = stringTablePart.SharedStringTable.ChildElements[Int32.Parse(value)].InnerText;
}
cellValues[colInx, rowInx] = value;
}
dt.Rows.Add(dataRow);
}
// Copy the array of strings into a DataTable
for (int col = 0; col < numOfColumns; col++)
dt.Columns.Add("Column_" + col.ToString());
for (int row = 0; row < numOfRows; row++)
{
DataRow dataRow = dt.NewRow();
for (int col = 0; col < numOfColumns; col++)
{
dataRow.SetField(col, cellValues[col, row]);
}
dt.Rows.Add(dataRow);
}
#if DEBUG
// Write out the contents of our DataTable to the Output window (for debugging)
string str = "";
for (rowInx = 0; rowInx < maxNumOfRows; rowInx++)
{
for (colInx = 0; colInx < maxNumOfColumns; colInx++)
{
object val = dt.Rows[rowInx].ItemArray[colInx];
str += (val == null) ? "" : val.ToString();
str += "\t";
}
str += "\n";
}
System.Diagnostics.Trace.WriteLine(str);
#endif
return dt;
}
}
private static void CalculateDataTableSize(string dimensions, ref int numOfColumns, ref int numOfRows)
{
// How many columns & rows of data does this Worksheet contain ?
// We'll read in the Dimensions string from the Excel file, and calculate the size based on that.
// eg "B1:F4" -> we'll need 6 columns and 4 rows.
//
// (We deliberately ignore the top-left cell address, and just use the bottom-right cell address.)
try
{
string[] parts = dimensions.Split(':'); // eg "B1:F4"
if (parts.Length != 2)
throw new Exception("Couldn't find exactly *two* CellAddresses in the dimension");
numOfColumns = 1 + GetColumnIndexByName(parts[1]); // A=1, B=2, C=3 (1-based value), so F4 would return 6 columns
numOfRows = GetRowIndexFromCellAddress(parts[1]);
}
catch
{
throw new Exception("Could not calculate maximum DataTable size from the worksheet dimension: " + dimensions);
}
}
public static int GetRowIndexFromCellAddress(string cellAddress)
{
// Convert an Excel CellReference column into a 1-based row index
// eg "D42" -> 42
// "F123" -> 123
string rowNumber = System.Text.RegularExpressions.Regex.Replace(cellAddress, "[^0-9 _]", "");
return int.Parse(rowNumber);
}
public static int GetColumnIndexByName(string cellAddress)
{
// Convert an Excel CellReference column into a 0-based column index
// eg "D42" -> 3
// "F123" -> 5
var columnName = System.Text.RegularExpressions.Regex.Replace(cellAddress, "[^A-Z_]", "");
int number = 0, pow = 1;
for (int i = columnName.Length - 1; i >= 0; i--)
{
number += (columnName[i] - 'A' + 1) * pow;
pow *= 26;
}
return number - 1;
}
}