我不知道以前是否有人遇到过此问题。基本上,我正在读取公式单元格值。原始单元格有两种字体样式Calibri
和Arial
。在这种情况下,它将以某种方式尝试保留样式,并将值作为XML样式表读取(下面的示例)。
就我而言,我不太在乎样式。在阅读单元格时是否有一种忽略样式的方法?
<r xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<t>XS-1000</t>
</r>
<r xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<rPr>
<b />
<i />
<sz val="18" />
<rFont val="Arial" />
<family val="2" />
</rPr>
<t>i</t>
</r>
<r xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<rPr>
<b />
<sz val="18" />
<rFont val="Arial" />
<family val="2" />
</rPr>
<t>™ ANALYZERS</t>
</r>
这是读取excel行的代码:
private List<string> ReadRow(ExcelRange cells, int row, int startColumn, int numberOfCols, bool skipEmptyCol = false)
{
if (row < 1)
throw new ArgumentException("invalid start line.", "startLine");
if (startColumn < 1)
throw new ArgumentException("invalid start column.", "startColumn");
if (numberOfCols < 1)
throw new ArgumentException("invalid number of columns.", "numberOfCols");
var rowData = new List<string>();
int currentColumn = startColumn;
while ((startColumn + numberOfCols > currentColumn))
{
var cellValueString = "";
var cellValue = (cells[row, currentColumn].Value ?? "").ToString();
if (string.IsNullOrWhiteSpace(cellValueString) && !skipEmptyCol) { break; }
rowData.Add(cellValueString);
currentColumn++;
}
return rowData;
}
这是单元格中的公式,其读取值来自:
=SUBSTITUTE(SUBSTITUTE('XEC PDF'!A3, "HEMATOLOGY CONTROL FOR ","")," and ","/")
答案 0 :(得分:0)
所以问题出在单元格中,因为有两种不同的字体样式(“ TM”是上标,其他一切正常)。执行ExcelWorkbook.Calculate()方法时,它将使用xml标记转换单元格值以保留样式。就我而言,我正在使用公式来提取值,并且只需要在报表上显示这些上标即可。所以我的解决方案是清除那些richText,放回正常值,然后运行Calculate()。另外,当我从合并的单元格中读取数据时,我遇到了另一个问题,它只是爆炸了。所以我也在下面添加了一个解决方案。
**您还可以通过添加标签并解析来从XML格式的文本中提取值,然后获取值(可以将其添加到公共数据成员属性中)。我已将解决方案发布到底部。
internal ImportFormulaSheetResponse ImportFormulaSheet(string formulaFilePath)
{
var impFormRes = new ImportFormulaSheetResponse();
try
{
using (var workbookFormula = new ExcelPackage(new FileInfo(formulaFilePath)))
using (var workbookOriginal = CreateExcelPackage(this.Stream))
{
List<string> sheetNames = new List<string>();
List<string> formulaSheets = new List<string>();
foreach (var worksheet in workbookOriginal.Workbook.Worksheets)
{
List<int> parameterCols = new List<int> { 1, 2, 17 };
int rowCount = worksheet.Dimension.End.Row;
foreach(int col in parameterCols)
{
for (int row = 14; row < rowCount; row++)
{
if (worksheet.Cells[row, col].IsRichText)
{
//removing super/sub script formatting from RichText Cell property
var celVal = worksheet.Cells[row, col].Value;
if (worksheet.Cells[row, col].Merge == true)
{
string range = GetMergedRange(worksheet, row, col);
worksheet.Cells[range].Merge = false;
}
worksheet.Cells[row, col].Clear();
worksheet.Cells[row, col].Value = celVal;
}
}
}
}
foreach (var worksheet in workbookFormula.Workbook.Worksheets)
{
if (worksheet.Name.Contains("Formula"))
{
workbookOriginal.Workbook.Worksheets.Add(worksheet.Name, worksheet);
formulaSheets.Add(worksheet.Name);
}
else
{
sheetNames.Add(worksheet.Name);
}
}
//Calculate so the formula references have updated values
workbookOriginal.Workbook.Calculate();
workbookOriginal.Save();
this.Stream = workbookOriginal.Stream;
return impFormRes;
}
}
catch (Exception ex)
{
impFormRes.Notifications.AddError(ex.Source, ex.Message);
return impFormRes;
}
}
/// <summary>
/// Find the merged range a specific cell it belongs to
/// </summary>
/// <returns>merged cell string</returns>
internal string GetMergedRange(ExcelWorksheet worksheet, int row, int col)
{
ExcelWorksheet.MergeCellsCollection mergedCells = worksheet.MergedCells;
foreach (var merged in mergedCells)
{
ExcelRange range = worksheet.Cells[merged];
ExcelCellAddress cell = new ExcelCellAddress(row, col);
if (range.Start.Row <= cell.Row && range.Start.Column <= cell.Column)
{
if (range.End.Row >= cell.Row && range.End.Column >= cell.Column)
{
return merged.ToString();
}
}
}
return "";
}
/////////////////////////////////////////////////////////////////
public class ExcelImport
{
//workbook.Calculate() generates xml style tag around a cell with multiple styling
//so add root tag to make it a proper xml document, parse and read root value
if (rowData[2].Contains("<"))
{
string myXML = "<root>" + rowData[2] + "</root>";
XDocument doc = XDocument.Parse(myXML);
InstrumentName = doc.Root.Value;
}
}