问题
How can I change the text color of CellValue in excel? I am able to change foreground color of a cell but it changes color of all text present inside the cell, which I don't want. I want to highlight only particular text inside the cell i.e CellValue text.
I am using below code to highlight cell text, how it can be done for 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;
}
I dont see any property of Style in 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;
}
Generated code from OpenXML Tool -
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;
回答1:
You have to go via the SharedStringItem
elements.
Such a SharedStringItem
can contain Run
elements.
You apply the styling on this Run
element.
It is important that your code also covers the situation where a SharedStringItem
does not contain any Run
child elements.
This is the case when the cell only holds text, without any formatted child elements.
Here you have to create a new Run in order to apply the styling.
The code below sets the color of the word RED to red for the cells in the first row using the Excel file as shown in the image below.
Cell A1
contains Run
elements, cell B1
doesn't.
The endresult looks like
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();
(I 'll leave the cleanup and exception handling in code above to you ...)
EDIT
For your specific case, having the cell value "Microsoft is great",
you'll have to split this string into separate parts and create a Run
for each part.
Only on the part having the text value 'Microsoft' you apply a custom font color.
The minimalistic code below shows this concept.
(This code can use some improvements, as it is better not to split on separate words, but you get the idea ...)
// 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);
}
The image below shows before and after.
EDIT
In response to your comment about how to loop over all cells in the Excel document; see the code below.
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 ...
}
}
}
}
}
来源:https://stackoverflow.com/questions/53214649/change-font-color-of-text-in-cellvalue-in-excel-openxml