在 Excel - OpenXml 中更改 CellValue 中文本的字体颜色

Change font color of text in CellValue in Excel - 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

中没有看到任何 属性 样式
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 元素上应用样式。

您的代码还涵盖 SharedStringItem 不包含任何 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 is great", 您必须将此字符串拆分为单独的部分,并为每个部分创建一个 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 ...
                }
            }
        }
    }
}