I'm using NPOI to programatically create an Excel file. One of the requirements is that it needs to be able to change the background of cells based on values - green for good numbers, red for bad, etc. I have everything working perfectly and can create formulas...but I cannot for the life of me find a formula that shows how to change background color. No matter how I try to google for the answer, everything just wants to show how to open Excel and use the conditional formatting wizard. I'm overlooking something? Is there a way I can see the formula that the conditional formatting wizard created and just copy and paste it into my code?
Below is a sample I set up to change the field to Pass/Fail...but my peeps like shiny colors to go along with it...
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sh = (XSSFSheet)wb.CreateSheet("ACT");
string cf = "IF(" + engCell + (detailRow.RowNum + 1) + #">17,""Pass :)"", ""Fail :("")";
detailRow.CreateCell(detailIdx);
detailRow.GetCell(detailIdx).SetCellType(CellType.Formula);
detailRow.GetCell(detailIdx++).SetCellFormula(cf);
I figured it out!!! I hope this may help others who are using NPOI XSSF for conditional formatting:
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sh = (XSSFSheet)wb.CreateSheet("ACT");
sh.CreateRow(0).CreateCell(0).SetCellValue(14);
sh.CreateRow(1).CreateCell(0).SetCellValue(20);
sh.CreateRow(2).CreateCell(0).SetCellValue(10);
sh.CreateRow(3).CreateCell(0).SetCellValue(23);
sh.CreateRow(4).CreateCell(0).SetCellValue(19);
sh.CreateRow(5).CreateCell(0).SetCellValue(14);
XSSFSheetConditionalFormatting sCF = (XSSFSheetConditionalFormatting)sh.SheetConditionalFormatting;
//Fill Green if Passing Score
XSSFConditionalFormattingRule cfGreen =
(XSSFConditionalFormattingRule)sCF.CreateConditionalFormattingRule(ComparisonOperator.GreaterThanOrEqual, "19");
XSSFPatternFormatting fillGreen = (XSSFPatternFormatting)cfGreen.CreatePatternFormatting();
fillGreen.FillBackgroundColor = IndexedColors.LightGreen.Index;
fillGreen.FillPattern = FillPattern.SolidForeground;
//Fill Red if Passing Score
XSSFConditionalFormattingRule cfRed =
(XSSFConditionalFormattingRule)sCF.CreateConditionalFormattingRule(ComparisonOperator.LessThan, "19");
XSSFPatternFormatting fillRed = (XSSFPatternFormatting)cfRed.CreatePatternFormatting();
fillRed.FillBackgroundColor = IndexedColors.Red.Index;
fillRed.FillPattern = FillPattern.SolidForeground;
CellRangeAddress[] cfRange = { CellRangeAddress.ValueOf("A1:A6") };
sCF.AddConditionalFormatting(cfRange, cfGreen, cfRed);
I am using Aspose Cells and I need to convert a particular column to text format, as the column consists of both numbers and Text, by default the column is taken as number format. I have used
Aspose.Cells.Style style = worksheet.Cells["A3"].GetStyle();
style.Number = 49;
worksheet.Cells["A3"].SetStyle(style);
the above code works only for particular Cell but I need to Set Text format entire column, I have tried using this
Aspose.Cells.Style style = workbook.Styles[workbook.Styles.Add()];
style.Number = 49; //Sets the Text format.
StyleFlag flag = new StyleFlag();
worksheet.Cells.ApplyColumnStyle(0, style, flag);
worksheet.Cells.ApplyColumnStyle(1, style, flag);
the above code not working. Is there any other way to fix this?
Thanks in Advance
I got solution for this,
var workbook = new Workbook();
var worksheet = workbook.Worksheets[0];
Aspose.Cells.Style TextStyle = workbook.CreateStyle();
TextStyle.Number = 49;
StyleFlag TextFlag = new StyleFlag();
TextFlag.NumberFormat = true;
worksheet.Cells.Columns[0].ApplyStyle(TextStyle, TextFlag);
worksheet.Cells.Columns[1].ApplyStyle(TextStyle, TextFlag);
How to create and set styles in Excel cells using C#?
I want to write something like "April 1st" with st as a superscript.
I would be using a string format not a date format.
I have tried http://msdn.microsoft.com/en-us/library/f1hh9fza.aspx but getting an The name 'Globals' does not exist in the current context error. I have added assembly Microsoft.Office.Interlop.Excel. Am I missing any other assembly?
Excel.Style style = Globals.ThisWorkbook.Styles.Add("NewStyle");
You actually don't want to change the font of the whole cell but you to change a portion of the text in the cell I take it.
You'll still need to retrieve the cell range and then adjust the characters within that range. here is an example where it's just adjusting the first cell. A1.
If you wanted to change the whole cell range to be superscript it would be done like this
currentRange.Font.Superscript = true;
void Main()
{
var app = new Application();
app.Visible = true;
var workbook = app.Workbooks.Add(1);
Sheets excelSheets = workbook.Worksheets;
string currentSheet = "Sheet1";
Worksheet worksheet1 = (Worksheet)excelSheets.get_Item(currentSheet);
worksheet1.Cells[1, 1] = "April 1st";
worksheet1.Cells[1, 2] = "April 2nd";
worksheet1.Cells[1, 3] = "April 3rd";
worksheet1.Cells[1, 4] = "April 4th";
// fill in the starting and ending range programmatically this is just an example.
string startRange = "A1";
string endRange = "A1";
Range currentRange = worksheet1.get_Range(startRange , endRange );
var text = currentRange.Text.ToString();
int length = text.Length;
int index = 0;
if(text.Contains("st"))
{
index =text.IndexOf("st");
}
//The other checks for "nd", "rd", "th" obviously check to see a # precedes these.
if(index > 0)
{
currentRange.get_Characters( index+1, 2).Font.Superscript = true;
}
}
As the MSDN article you've linked to states:
Applies to: The information in this topic applies to document-level
projects and application-level projects for Office 2013 and Office
2010. See Features Available by Office Application and Project Type.
To use Globals class you have to create Office project. For another reference you can check this question about creating Office add-in:
Globals.ThisAddin.Application can be only used in VSTO Add-In
I am trying to replace formulas on column D with their values.
eg. currently D1 = C1 / 2
If C1 = 10, I want D1 to be 5
I need to do this because I need to delete the column C.
I tried changing the format to Text like below but it doesn't seem to replace formulas with their values
Excel.Style style = workbook.Styles.Add("styleText", Missing.Value);
style.NumberFormat = "#";
Excel.Range range = (Excel.Range)sheet.get_Range("D1", Missing.Value);
range.Style = style;
Here's a macro in VBA that does what you need... It's VB code but I dont think woould be a problem to translate it in C#
Sub ValuesOnly()
Dim rRange As Range
On Error Resume Next
Set rRange = Application.InputBox(Prompt:="Select the formulas", Title:="VALUES ONLY", Type:=8)
If rRange Is Nothing Then Exit Sub
rRange = rRange.Value
End Sub
Another way to do it is to simply mimic the command Paste Special -> Values. I have just recorded a macro that does it (C5 in my sample is a cell that contains a function)
Sub Macro1()
Range("C5").Select
Selection.Copy
Range("D5").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
End Sub
How do you format a comment??
Here is the solution I got, thanks to Lorenzo
private static void ReplaceFormulasWithValues(ref Excel.Worksheet sheet, char column)
{
Excel.Range range = (Excel.Range)sheet.get_Range(column + "1", Missing.Value).EntireColumn;
range.Copy(Missing.Value);
range.PasteSpecial(Microsoft.Office.Interop.Excel.XlPasteType.xlPasteValues,
Microsoft.Office.Interop.Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone, false, false);
}
This is another way to do it (C1 contains a formula, the result is placed in D1)
static void Main( string[] args ) {
string fileName = #"D:\devprj\Temp\TempProject\bin\Debug\Cartel1.xlsx";
Application ac = new Application();
Workbook wb = ac.Workbooks.Open( fileName );
Worksheet ws = wb.Sheets[1];
Range rangeOrigin = ws.get_Range( "C1" );
Range rangeDestination = ws.get_Range( "D1" );
rangeDestination.Value = rangeOrigin.Value2;
wb.Save();
}
You can't just change the display style, because that doesn't change the content of the cell. When you're doing this manually in Excel you need to copy the column and then choose Paste Special -> Values to paste the values rather than the formulae. I imagine there's a programatic way to do the same operation.
I am losing the leading zeros when I copy values from a datatable to an Excel sheet. That's because probably Excel treats the values as a number instead of text.
I am copying the values like so:
myWorksheet.Cells[i + 2, j] = dtCustomers.Rows[i][j - 1].ToString();
How do I format a whole column or each cell as Text?
A related question, how to cast myWorksheet.Cells[i + 2, j] to show a style property in Intellisense?
Below is some code to format columns A and C as text in SpreadsheetGear for .NET which has an API which is similar to Excel - except for the fact that SpreadsheetGear is frequently more strongly typed. It should not be too hard to figure out how to convert this to work with Excel / COM:
IWorkbook workbook = Factory.GetWorkbook();
IRange cells = workbook.Worksheets[0].Cells;
// Format column A as text.
cells["A:A"].NumberFormat = "#";
// Set A2 to text with a leading '0'.
cells["A2"].Value = "01234567890123456789";
// Format column C as text (SpreadsheetGear uses 0 based indexes - Excel uses 1 based indexes).
cells[0, 2].EntireColumn.NumberFormat = "#";
// Set C3 to text with a leading '0'.
cells[2, 2].Value = "01234567890123456789";
workbook.SaveAs(#"c:\tmp\TextFormat.xlsx", FileFormat.OpenXMLWorkbook);
Disclaimer: I own SpreadsheetGear LLC
If you set the cell formatting to Text prior to adding a numeric value with a leading zero, the leading zero is retained without having to skew results by adding an apostrophe. If you try and manually add a leading zero value to a default sheet in Excel and then convert it to text, the leading zero is removed. If you convert the cell to Text first, then add your value, it is fine. Same principle applies when doing it programatically.
// Pull in all the cells of the worksheet
Range cells = xlWorkBook.Worksheets[1].Cells;
// set each cell's format to Text
cells.NumberFormat = "#";
// reset horizontal alignment to the right
cells.HorizontalAlignment = XlHAlign.xlHAlignRight;
// now add values to the worksheet
for (i = 0; i <= dataGridView1.RowCount - 1; i++)
{
for (j = 0; j <= dataGridView1.ColumnCount - 1; j++)
{
DataGridViewCell cell = dataGridView1[j, i];
xlWorkSheet.Cells[i + 1, j + 1] = cell.Value.ToString();
}
}
Solution that worked for me for Excel Interop:
myWorksheet.Columns[j].NumberFormat = "#"; // column as a text
myWorksheet.Cells[i + 2, j].NumberFormat = "#"; // cell as a text
This code should run before putting data to Excel. Column and row numbers are 1-based.
A bit more details. Whereas accepted response with reference for SpreadsheetGear looks almost correct, I had two concerns about it:
I am not using SpreadsheetGear. I was interested in regular Excel
communication thru Excel interop without any 3rdparty libraries,
I was searching for the way to format column by number, not using
ranges like "A:A".
Before your write to Excel need to change the format:
xlApp = New Excel.Application
xlWorkSheet = xlWorkBook.Sheets("Sheet1")
Dim cells As Excel.Range = xlWorkSheet.Cells
'set each cell's format to Text
cells.NumberFormat = "#"
'reset horizontal alignment to the right
cells.HorizontalAlignment = Excel.XlHAlign.xlHAlignRight
I've recently battled with this problem as well, and I've learned two things about the above suggestions.
Setting the numberFormatting to # causes Excel to left-align the value, and read it as if it were text, however, it still truncates the leading zero.
Adding an apostrophe at the beginning results in Excel treating it as text and retains the zero, and then applies the default text format, solving both problems.
The misleading aspect of this is that you now have a different value in the cell. Fortuately, when you copy/paste or export to CSV, the apostrophe is not included.
Conclusion: use the apostrophe, not the numberFormatting in order to retain the leading zeros.
Use your WorkSheet.Columns.NumberFormat, and set it to string "#", here is the sample:
Excel._Worksheet workSheet = (Excel._Worksheet)_Excel.Worksheets.Add();
//set columns format to text format
workSheet.Columns.NumberFormat = "#";
Note: this text format will apply for your hole excel sheet!
If you want a particular column to apply the text format, for example, the first column, you can do this:
workSheet.Columns[0].NumberFormat = "#";
or this will apply the specified range of woorkSheet to text format:
workSheet.get_Range("A1", "D1").NumberFormat = "#";
if (dtCustomers.Columns[j - 1].DataType != typeof(decimal) && dtCustomers.Columns[j - 1].DataType != typeof(int))
{
myWorksheet.Cells[i + 2, j].NumberFormat = "#";
}
I know this question is aged, still, I would like to contribute.
Applying Range.NumberFormat = "#" just partially solve the problem:
Yes, if you place the focus on a cell of the range, you will read text in the format menu
Yes, it align the data to the left
But if you use the type formula to check the type of the value in the cell, it will return 1 meaning number
Applying the apostroph behave better. It sets the format to text, it align data to left and if you check the format of the value in the cell using the type formula, it will return 2 meaning text
//where [1] - column number which you want to make text
ExcelWorksheet.Columns[1].NumberFormat = "#";
//If you want to format a particular column in all sheets in a workbook - use below code. Remove loop for single sheet along with slight changes.
//path were excel file is kept
string ResultsFilePath = #"C:\\Users\\krakhil\\Desktop\\TGUW EXCEL\\TEST";
Excel.Application ExcelApp = new Excel.Application();
Excel.Workbook ExcelWorkbook = ExcelApp.Workbooks.Open(ResultsFilePath);
ExcelApp.Visible = true;
//Looping through all available sheets
foreach (Excel.Worksheet ExcelWorksheet in ExcelWorkbook.Sheets)
{
//Selecting the worksheet where we want to perform action
ExcelWorksheet.Select(Type.Missing);
ExcelWorksheet.Columns[1].NumberFormat = "#";
}
//saving excel file using Interop
ExcelWorkbook.Save();
//closing file and releasing resources
ExcelWorkbook.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(ExcelWorkbook);
ExcelApp.Quit();
Marshal.FinalReleaseComObject(ExcelApp);
You need to format the column to be a string.
You can use the link https://supportcenter.devexpress.com/ticket/details/t679279/import-from-excel-to-gridview
For converting the ExcelDataSource, you can also refer to https://supportcenter.devexpress.com/ticket/details/t468253/how-to-convert-exceldatasource-to-datatable