c# - 在 Excel 中更改 CellValue 中文本的字体颜色 - OpenXml
问题描述
如何更改 Excel 中 CellValue 的文本颜色?我可以更改单元格的前景色,但它会更改单元格内所有文本的颜色,这是我不想要的。我只想突出显示单元格内的特定文本,即 CellValue 文本。
我正在使用下面的代码突出显示单元格文本,如何为 CellValue 完成?
foreach (DocumentFormat.OpenXml.Spreadsheet.Cell currentCell in allCells)
{
Fill fill = new Fill()
{
PatternFill = new PatternFill
{
PatternType = PatternValues.Solid,
ForegroundColor = new ForegroundColor() { Rgb = "FFFF00" }
}
};
styleSheet.Fills.AppendChild(fill);
//Adding the CellFormat which uses the Fill element
CellFormats cellFormats = styleSheet.CellFormats;
CellFormat cf = new CellFormat();
cf.FillId = styleSheet.Fills.Count;
cellFormats.AppendChild(cf);
currentCell.StyleIndex = styleSheet.CellFormats.Count;
}
我在 CellValue 中没有看到 Style 的任何属性
CellValue currentCellValue = currentCell.GetFirstChild<CellValue>();
if (currentCell.DataType == CellValues.SharedString) // cell has a cell value that is a string, thus, stored else where
{
data = doc.WorkbookPart.GetPartsOfType<SharedStringTablePart>().FirstOrDefault().SharedStringTable.ElementAt(int.Parse(currentCellValue.Text)).InnerText;
}
从 OpenXML 工具生成的代码 -
SharedStringTable sharedStringTable1 = new SharedStringTable(){ Count = (UInt32Value)1U, UniqueCount = (UInt32Value)1U };
SharedStringItem sharedStringItem1 = new SharedStringItem();
Run run1 = new Run();
RunProperties runProperties1 = new RunProperties();
FontSize fontSize3 = new FontSize(){ Val = 11D };
Color color3 = new Color(){ Rgb = "FFFF0000" };
RunFont runFont1 = new RunFont(){ Val = "Calibri" };
FontFamily fontFamily1 = new FontFamily(){ Val = 2 };
FontScheme fontScheme4 = new FontScheme(){ Val = FontSchemeValues.Minor };
runProperties1.Append(fontSize3);
runProperties1.Append(color3);
runProperties1.Append(runFont1);
runProperties1.Append(fontFamily1);
runProperties1.Append(fontScheme4);
Text text1 = new Text();
text1.Text = "Microsoft";
run1.Append(runProperties1);
run1.Append(text1);
Run run2 = new Run();
RunProperties runProperties2 = new RunProperties();
FontSize fontSize4 = new FontSize(){ Val = 11D };
Color color4 = new Color(){ Theme = (UInt32Value)1U };
RunFont runFont2 = new RunFont(){ Val = "Calibri" };
FontFamily fontFamily2 = new FontFamily(){ Val = 2 };
FontScheme fontScheme5 = new FontScheme(){ Val = FontSchemeValues.Minor };
runProperties2.Append(fontSize4);
runProperties2.Append(color4);
runProperties2.Append(runFont2);
runProperties2.Append(fontFamily2);
runProperties2.Append(fontScheme5);
Text text2 = new Text(){ Space = SpaceProcessingModeValues.Preserve };
text2.Text = " is great";
run2.Append(runProperties2);
run2.Append(text2);
sharedStringItem1.Append(run1);
sharedStringItem1.Append(run2);
sharedStringTable1.Append(sharedStringItem1);
sharedStringTablePart1.SharedStringTable = sharedStringTable1;
解决方案
你必须通过SharedStringItem
元素。
这样的一个SharedStringItem
可以包含Run
元素。您在此元素
上应用样式。Run
重要的是,您的代码还涵盖 aSharedStringItem
不包含任何子Run
元素的情况。当单元格仅包含文本而没有任何格式化的子元素时就是这种情况。
在这里,您必须创建一个新的 Run 才能应用样式。
下面的代码使用 Excel 文件将第一行中的单元格的单词 RED 的颜色设置为红色,如下图所示。
单元格A1
包含Run
元素,单元格B1
不包含。
最终结果看起来像
String pathToYourExcelFile = @"C:\Folder\ExcelFile.xlsx";
using (SpreadsheetDocument document = SpreadsheetDocument.Open(pathToYourExcelFile, true))
{
WorkbookPart workbook = document.WorkbookPart;
WorksheetPart firstWorksheet = document.WorkbookPart.WorksheetParts.FirstOrDefault();
SharedStringTablePart stringTable = workbook.GetPartsOfType<SharedStringTablePart>().FirstOrDefault();
IEnumerable<Row> rows = firstWorksheet.Worksheet.GetFirstChild<SheetData>().Elements<Row>();
Row firstRow = rows.FirstOrDefault();
foreach (Cell cell in firstRow.Elements<Cell>())
{
foreach (CellValue cellValue in cell.Elements<CellValue>())
{
IEnumerable<SharedStringItem> sharedStrings =
stringTable.SharedStringTable.Elements<SharedStringItem>()
.Where((o, i) => i == Convert.ToInt32(cellValue.InnerText));
foreach (SharedStringItem sharedString in sharedStrings)
{
IEnumerable<Run> runs = sharedString.Elements<Run>();
if (runs.Count() > 0)
{
foreach (Run run in runs)
{
if (run.InnerText == "RED")
{
RunProperties properties = run.RunProperties ?? new RunProperties();
Color color = properties.Elements<Color>().FirstOrDefault();
if (color != null)
{
properties.RemoveChild<Color>(color);
}
properties.Append(new Color { Rgb = "FFFF0000" }) ;
}
}
}
else
{
// No Runs, only text; create a Run.
Text text = new Text(sharedString.InnerText);
sharedString.RemoveAllChildren();
Run run = new Run();
run.Append(text);
run.RunProperties = new RunProperties();
run.RunProperties.Append(new Color { Rgb = "FFFF0000" }) ;
sharedString.Append(run);
}
}
}
}
document.Save();
(我将把上面代码中的清理和异常处理留给你……)
编辑
对于您的特定情况,具有单元格值“Microsoft 很棒”,您必须将此字符串拆分为单独的部分并Run
为每个部分创建一个。仅在具有文本值“Microsoft”的部分上应用自定义字体颜色。
下面的简约代码显示了这个概念。
(此代码可以使用一些改进,因为最好不要拆分为单独的单词,但你明白了......)
// No Runs, only text.
const String MS = "Microsoft";
String innerText = sharedString.InnerText;
if (innerText.IndexOf(MS, StringComparison.OrdinalIgnoreCase) >= 0)
{
sharedString.RemoveAllChildren();
String[] parts = innerText.Split(' ');
for (Int32 i = 0; i < parts.Length; i++)
{
String part = parts[i];
Text text = new Text((i > 0 ? " " : String.Empty) + part);
text.Space = SpaceProcessingModeValues.Preserve;
Run run = new Run();
run.Append(text);
if (part.Equals(MS, StringComparison.OrdinalIgnoreCase))
{
run.RunProperties = new RunProperties();
run.RunProperties.Append(new Color { Rgb = "FFFF0000" }) ;
}
sharedString.Append(run);
}
下图显示了之前和之后。
编辑
回应您关于如何遍历 Excel 文档中所有单元格的评论;请参阅下面的代码。
String pathToYourExcelFile = @"C:\Folder\ExcelFile.xlsx";
using (SpreadsheetDocument document = SpreadsheetDocument.Open(pathToYourExcelFile, true))
{
WorkbookPart workbook = document.WorkbookPart;
// Loop over all worksheets.
IEnumerable<WorksheetPart> worksheets = document.WorkbookPart.WorksheetParts;
foreach (WorksheetPart worksheet in worksheets)
{
// Loop over all rows.
IEnumerable<Row> rows = worksheet.Worksheet.GetFirstChild<SheetData>().Elements<Row>();
foreach (Row row in rows)
{
// Loop over all cells.
foreach (Cell cell in row.Elements<Cell>())
{
// Loop over all cell values.
foreach (CellValue cellValue in cell.Elements<CellValue>())
{
// Apply content formatting as in code above ...
}
}
}
}
}
推荐阅读
- r - R中函数运行时的异常值
- parsing - 逐字节搜索文件的正确方法是什么?
- wordpress - 在帖子页面上预填充 Woocommerce 简短描述
- firebase - 从 Firestore Flutter 中的文档中获取用户名
- java - 无法解析方法'toString()
- ios - 使用 Flutter 为 iOS 构建时,我在哪里可以查看 XCode 运行脚本阶段的输出?
- python - 如何捕获 Key Vault SecretClient 错误 Azure Python SDK?
- javascript - 创建一个迭代 - Javascipt
- javascript - Vue3 - 获取 API 后在 V-for 上调用函数
- github - 在 GitHub 工作流上自动设置发布标签