I'm using NPOI and C# and cannot seem to get AutoSizeColumn to size the columns appropriately. I've followed the suggestions I can find, set the font up front in the styles, added content after the styles are applied, auto-sized the columns before write (after all data is added) and still the columns are too narrow. Below is a demonstration of the problem:
public void ShowBug()
{
IWorkbook workbook;
workbook = new XSSFWorkbook();
// Create a base font
IFont boldFont = workbook.CreateFont();
boldFont.FontHeightInPoints = 11;
boldFont.FontName = "Calibri";
boldFont.Boldweight = (short)FontBoldWeight.Bold;
// Create a base style
ICellStyle boldStyle = workbook.CreateCellStyle();
boldStyle.SetFont(boldFont);
// Create a simple cell style using the base style
ICellStyle simpleStyle = workbook.CreateCellStyle();
simpleStyle.CloneStyleFrom(boldStyle);
// Create a sheet in the workbook
ISheet excelSheet = workbook.CreateSheet("Demo");
// Create a single row
IRow row = excelSheet.CreateRow(0);
// Create a single cell inside the row
ICell cell = row.CreateCell(0);
cell.SetCellType(CellType.String);
cell.CellStyle = simpleStyle;
cell.SetCellValue("This is an icredibly long text value for this column - and apparently too long");
// Autosize the column and create the file, after the output is produced
using (var fs = new FileStream("BugReport.xlsx", FileMode.Create, FileAccess.Write))
{
excelSheet.AutoSizeColumn(0, true);
workbook.Write(fs);
}
}
This code shows up in Excel like this:
Result of Code
So, what am I missing? What am I doing wrong?
I am using this approach to auto size the column header
XSSFSheet sheet = (XSSFSheet)workbook.CreateSheet("Demo");
sheet.AutoSizeColumn(“header1”); // Remove Boolean value which you are passing
Related
I am creating an Excel spreadsheet (XLSX) from an existing template and adding a dataset to a table on one of the worksheets.
I have been able to programmatically set the active sheet, but I can't set where the scroll position of the sheet is so that the last rows of data are displayed when someone opens the spreadsheet in Excel.
I'm adding 5000+ rows but when someone opens the file in Excel, the scroll position is where it was when the original template was saved. The cell I set to selected is indeed selected but it's off screen.
Here's my code:
using (var workbook = new XLWorkbook(fileInfo.FullName))
{
workbook.Properties.Author = _configuration.GetSection("ExcelAuthor").Value;
var workSheet = workbook.Worksheet(_configuration.GetSection("ExcelWorkSheetName").Value);
var table = workSheet.Table(_configuration.GetSection("ExcelTableName").Value);
var range = table.ReplaceData(data.Tables[0]);
//Set the sheet as the active sheet
foreach (var sheet in workbook.Worksheets)
{
var isCurrentSheet = sheet.Equals(workSheet);
sheet.SetTabActive(isCurrentSheet);
sheet.SetTabSelected(isCurrentSheet);
}
//workSheet.ActiveCell = range.LastCell();
workSheet.Cell(range.LastCell().Address).Select();
//range.LastCell().Select();
//range.LastCell().SetActive();
path = string.Format("{0} - {1}.xlsx", _configuration.GetSection("FileNamePrefix").Value, DateTime.Now.ToString("yyyy-MM-dd"));
path = string.Format("{0}\\{1}", _configuration.GetSection("OutputFolder").Value.TrimEnd(new[] { '/', '\\' }), path);
workbook.SaveAs(path);
};
I submitted a pull request and this is fixed in https://github.com/ClosedXML/ClosedXML/pull/1561
I'm not sure that it's possible to set the exact scroll position, but you can set the currently selected cell.
var wb = new XLWorkbook();
var wsActiveCell = wb.AddWorksheet("Set Active Cell");
wsActiveCell.Cell("B2000").SetActive();
Reference: https://github.com/ClosedXML/ClosedXML/wiki/Selecting-Cells-and-Ranges
I'm trying to verify that a cell in a row is not null. If it is null, I want to change the background colour of the cell to red. After reading how to do that, I have come up with the following code:
public int verifyImportFile(FileUpload fup)
{
int status = 0;
//check if there is actually a file being uploaded
if (fup.HasFile)
{
//load the uploaded file into the memorystream
using (MemoryStream stream = new MemoryStream(fup.FileBytes))
//Lets the server know to use the excel package
using (ExcelPackage xlPackage = new ExcelPackage(stream))
{
//Gets the first worksheet in the workbook
ExcelWorksheet worksheet = xlPackage.Workbook.Worksheets[1];
//Gets the row count
var rowCnt = worksheet.Dimension.End.Row;
//Gets the column count
var colCnt = worksheet.Dimension.End.Column;
//Beginning the loop for data gathering
for (int i = 2; i < rowCnt; i++) //Starts on 2 because excel starts at 1, and line 1 is headers
{
//If there is no value in column 3, proceed
if (worksheet.Cells[i, 3].Value == null)
{
worksheet.Cells[i, 3].Style.Fill.PatternType = ExcelFillStyle.Solid;
worksheet.Cells[i,3].Style.Fill.BackgroundColor.SetColor(Color.Red);
status = 1;
}
}
xlPackage.Save();
}
}
return status;
}
What I do know from testing is that if a null value is found, it enters the if statement that checks for nulls. It seems to be running the code to change the background colour. After it loops through the entire excel sheet, the variable status does change to 1 and is displayed in a popup.
From my understanding of how to do this, it is running properly but the background colour stays white.
Your code is correct as far as setting the background color assuming it is being hit which have confirmed.
But how are you actually saving out the file? Once you load to a MemoryStream the connection to the original byte array is severed. You need to do a SaveAs() or GetAsByteArray() call like this:
xlPackage.SaveAs(new FileInfo(#"c:\temp\myFile.xls"));
Calling Save() just writes to the MemoryStream.
Hopefully this works.
worksheet.Cells[i, 3].Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red)
I'm trying to create a simple example with #officewriter #excelwriter and having trouble using the styles. Not sure why.
ExcelApplication XLAPP = new ExcelApplication();
Workbook WB = XLAPP.Create();
Worksheet WKST = WB.Worksheets[0];
DataSet ds = <...some valid dataset with 2 columns....>
DataView dv = ds.Tables[0].DefaultView;
DataImportProperties props = WB.CreateDataImportProperties();
SoftArtisans.OfficeWriter.ExcelWriter.Style dataStyle = WB.CreateStyle();
props.UseColumnNames = true;
dataStyle.BackgroundColor = Color.SystemColor.Red;
dataStyle.CellLocked = true;
Area importArea = WKST.ImportData(dv, WKST.Cells[0, 0],props);
importArea.ApplyStyle(dataStyle);
XLAPP.Save(WB, Page.Response, "Output.xls", false);
Here's the problem: the color style works in the output but the CellLocked style does not. Why?
Thanks for any help. Frustrated - I thought this was a simple example!
ExcelWriter is designed to mimic Excel, so usually the steps that you need to take in Excel to active certain properties are the same steps that you need to take in ExcelWriter.
In Excel, all the cells in a worksheet have the locked style property set, but that property will not take effect until the worksheet is protected. (Right click on a cell and go to Format Cells > Protection - the Locked property is checked, but the cells are not locked until you go to Review > Protect Sheet).
Similarly, in ExcelWriter, all the cells in Worksheet.Cells have the Style.CellLocked set to true by default, but that property will not take effect until Worksheet.Protect() is called. Once you protect the sheet, the cells should be locked.
ExcelApplication xlapp = new ExcelApplication();
Workbook wb = xlapp.Create(ExcelApplication.FileFormat.Xlsx);
Worksheet ws = wb.Worksheets["Sheet1"];
//Currently, all the cells have default "locked" style set to true
//Protecting the worksheet will activate this property
ws.Protect("MyPassword");
xlapp.Save(wb, "ProtectedWorksheet.xlsx");
Since all the cells default to Locked, if you want to lock only an area of cells and not the entire worksheet, you will need to set Style.CellLocked to false on any cells that you want to leave unlocked. When the worksheet is protected, these cells will remain editable.
ExcelApplication xlapp = new ExcelApplication();
Workbook wb = xlapp.Open("MyWorkbook.xlsx");
Worksheet ws = wb.Worksheets[0];
//Create a style that will leave certain cells unlocked
//when the worksheet is protected
Style unlockStyle = wb.CreateStyle();
unlockStyle.CellLocked = false;
//Select the area that will be left unprotected
//Apply the style to that area
Area unlockedArea = ws.PopulatedCells;
unlockedArea.ApplyStyle(unlockStyle);
//Protect the worksheet
ws.Protect("MyPassword");
xlapp.Save(wb, "MyNewWorkbook.xlsx");
For more about protecting worksheets, we have a guide in our documentation: Protecting Your Worksheet.
Note: I work for SoftArtisans, makers of OfficeWriter.
I am working on a project that writes data to an Excel file.
Everything is finished now, however I need a few cells with a bigger size than the rest (title, etc).
I have read about this about the internet, but I keep having the same problem: when I execute my code (see below for what I have tried), everything in the worksheet becomes larger.
What I already have tried:
worksheet.Rows[1].Cells[7].Style.Font.Size = 20;
worksheet.get_Range("A7", "A7").Style.Font.Size = 20;
None of this seems to work; what is the correct way to increase a cell's font size?
I had to use:
worksheet.get_Range("A7", "A7").Cells.Font.Size = 20;
If the data is consistent and will always be written to the same cells then this is the simplest solution - works well for product details / contact info type exporting
// set cell A7
worksheet.get_Range("A7", "A7").Font.Size = 20;
// set cells A7, A8
worksheet.get_Range("A7", "A8").Font.Size = 20;
// set cells A7, B7
worksheet.get_Range("A7", "B7").Font.Size = 20;
// set cells A7, A8, B7, B8
worksheet.get_Range("A7", "B8").Font.Size = 20;
If the data varies and will sometimes be written to multiple rows/columns then something like this is more simple - works well for dataset / shopping list type exporting
int RowNum;
int ColNum;
// some code to set variables
worksheet.Cells[RowNum, ColNum].Font.Size = 20;
I would just use:
worksheet.Range["A7"].Style.Font.Size = 20;
edit: sorry, wrong brackets
When working with interop excel, try not to write your code with "two dots" in order to clean interop excel objects.
This also helps having your code more readable.
Anyway, to answer your question, and using what I have pointed out... all you have to do is:
//Declare your variables
Application excel = null;
Workbook excelworkBook = null;
Range excelCellrange = null;
Worksheet worksheet = null;
Font excelFont =null;
//start your application
excel = new Application();
try
{
...
//your code goes here...
excelCellrange = worksheet.Range[worksheet.Cells[1,7],worksheet.Cells[1,7]];
excelFont = excelCellrange.Font;
excelfont.Size = 20;
...
...
}
catch(Exception ex){
}
finally{
//here put something to clean the interop objects as the link above.
...
Marshal.ReleaseComObject(excelfont);
...
}
I wanted to add formulas to an Excel workSheet.
I managed to do so with the Formula property.
The problem is that when I open the worksheet in Excel, I can see that the formula works - but I can only see the result in the cell. I can't see the formula that was calculated in the Formula Bar at the top of Excel.
Obviously if I enter a formula in Excel itself I can see the result in the cell and the formula in the Formula Bar.
Some of my code:
for (int i = 0; i < nOfColumns / 3; i++)
{
Range cells = workSheet.Range[workSheet.Cells[2, i * 3 + 3], workSheet.Cells[lastRowNumber, i * 3 + 3]];
cells.FormulaR1C1 = "=IF(EXACT(RC[-2],RC[-1]),TRUE,ABS(RC[-2]/RC[-1]-1))";
}
below is a test code. even after I save the workbook - the FormulaHidden is false and I can successfully retrieve the formula insterted. really frustrated
Microsoft.Office.Interop.Excel.Application excelApp = null;
Workbooks workBooks = null;
Workbook workBook = null;
Worksheet workSheet;
try
{
excelApp = new Microsoft.Office.Interop.Excel.Application();
excelApp.DisplayAlerts = false;
workBooks = excelApp.Workbooks;
workBook = workBooks.Open(filePath, AddToMru: false);
workSheet = workBook.Worksheets.get_Item(1);
int nOfColumns = workSheet.UsedRange.Columns.Count;
int lastRowNumber = workSheet.UsedRange.Rows.Count;
Range rng = workSheet.Range["C1"];
rng.Formula = "=SUM(B2:B4)";
String formula = rng.Formula; //retrieve the formula successfully
rng.FormulaHidden = false;
workSheet.Unprotect();
workBook.SaveAs(filePath, AccessMode: XlSaveAsAccessMode.xlExclusive);
formula = rng.Formula; //retrieve the formula successfully
bool hidden = rng.FormulaHidden;
}
catch (Exception e)
{
throw;
}
finally
{
if (workBook != null)
{
workBook.Close();
workBook = null;
}
if (workBooks != null)
{
workBooks.Close();
workBooks = null;
}
if (excelApp != null)
{
excelApp.Quit();
excelApp = null;
}
}
}
Anyone know how to make the formula shown, when adding the formulas programatically ?
finally !!! figured it out. this behavior is caused by the SaveAs flags.
changed
workBook.SaveAs(filePath, AccessMode: XlSaveAsAccessMode.xlExclusive);
to
workBook.SaveAs(filePath, AccessMode: XlSaveAsAccessMode.xlShared);
now the only thing left is to understand what exactly is the different between the two flags. :)
Hiding the formula (by checking Hidden checkbox on Format Cells dialog) & protecting the worksheet (thereafter) will cause the formula to not show in the formula bar.
Example VBA code
Range("C1").FormulaHidden = True 'set this property to false to make formula visible.
Sheet1.Protect
EDIT: In order to see the formula in the formula bar
Range("C1").FormulaHidden = False
Sheet1.Unprotect
Go to the Formula tab on the tool bar, and click "Show Formulas".
I think localization could be involved in this weird behaviour.
Some time ago, working in Excel, I had the impression that formulas got stored in localized language (I was using italian), then undergo a conversion when compiled. This could make sense, because localized constants are an essential part of the spreadsheet data.
I'm sorry I haven't now Excel available, so I can't be more precise, but I think you could try to localize to english your spreadsheet, or set the formula text in your local language.