Changing font size of one cell in excel using C# - c#

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);
...
}

Related

Print Options(Excel Iterop) Issue with horizontal page breaks?

I am having problems with setting horizontal page breaks. No matter what row I set the first page break to it ALWAYS is set the row 87
This is the code I am using. (I checked to see if I was accidentally setting the page break again below this code, but I was not) So this is all of the code I am using to setup the print settings.
int pageCount = 2;
string defprinter = null;
defprinter = xlApplication.ActivePrinter;
xlWorkSheet.ResetAllPageBreaks();
xlApplication.ActivePrinter = defprinter;
var with = xlWorkSheet.PageSetup;
with.PaperSize = Excel.XlPaperSize.xlPaperA4;
with.Orientation = Excel.XlPageOrientation.xlPortrait;
// Fit Sheet on One Page
with.Zoom = false;
with.FitToPagesWide = 1;
with.PrintArea = #"$A$1:$I$" + (pageCount * 71);
with.FitToPagesTall = pageCount;
xlWorkSheet.HPageBreaks.Add(xlWorkSheet.Range["A72"]);
xlWorkSheet.HPageBreaks.Add(xlWorkSheet.Range["A143"]);
// Normal Margins
with.LeftMargin = xlApplication.InchesToPoints(0.5);
with.RightMargin = xlApplication.InchesToPoints(0.5);
with.TopMargin = xlApplication.InchesToPoints(0.5);
with.BottomMargin = xlApplication.InchesToPoints(0.5);
I have spent the better part of two days trying all different settings with no luck. No matter what I do, the first PageBreak is always set the row 87 and not row 72.
Any suggestions would be greatly appreciated.
EDIT: Tried this code on a different PC today and it works as it should. So now the issue is identified as being something to do with what is going on in Excel on that particular machine. OS is Windows 10 BTW.
So even though it works, this is still an issue as I can't have it sporadically working on some users PC's and not on others.

Unable to change cell background colour, EPPlus in C#

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)

How can I add an image to my sheet without being prompted to replace contents of the (empty) destination cells (EPPlus)?

When I open the Excel file I generate using EPPlus (C#), I get "Do you want to replace the contents of the destination cells in [... .xlsx]PivotTable?"
As you can see in the screen shot below, there is nothing in the cell where I want the image to display. Even when I push the image beyond the outer edge of the PivotTable, I get this message (I had been placing beneath column C/3). When I select yes to the dialog quoted above, the image is finally placed on the sheet (if I select "no" it is not added), and the sheet looks like this:
This is the code I'm using to add the image:
int imageCol = _grandTotalsColumnPivotTable + 1; // -1; <= I really want it to be this
AddImage(pivotTableWorksheet, 1, imageCol);
. . .
private void AddImage(ExcelWorksheet oSheet, int rowIndex, int colIndex)
{
var excelImage = oSheet.Drawings.AddPicture("PRO*ACT Logo", _logo);
excelImage.From.Column = colIndex - 1;
excelImage.From.Row = rowIndex - 1;
excelImage.SetSize(130, 100);
excelImage.From.ColumnOff = Pixel2MTU(2);
excelImage.From.RowOff = Pixel2MTU(2);
}
public int Pixel2MTU(int pixels)
{
int mtus = pixels * 9525;
return mtus;
}
How can I either get the message to not display (programmatically, this can't be something the user needs to do) and "just do it" or let it know that there is nothing in that location, anyway?
UPDATE
This is apparently not the problem; I tried to delete this post, but can't, since it has an answer. Even when I comment out the writing of the image, I get it. And trying to prevent messages like so:
_xlApp.DisplayAlerts = false;
...does not work, either - I still get it.
Apparently the problem is elsewhere, but I don't know where.
UPDATE 2
It was a case of hidden data underneath the PivotTable; once I got rid of that, the problem went away. IOW, the problem was with my code, not with EPPlus.
I use this code to add an image to Excel. It does not asks me to replace content. But I do not use PivotTables. Maybe that would make a difference.
using (System.Drawing.Image image = System.Drawing.Image.FromFile(HttpContext.Current.Server.MapPath("test.png")))
{
var excelImage = ws.Drawings.AddPicture("My Logo", image);
excelImage.SetPosition(1, 0, 5, 0);
}

Adding formula to Excel with C# - making the formula shown

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.

How to "clean up" Microsoft.Office.Interop.Excel.Workbook

So I have a Microsoft.Office.Interop.Excel.Workbook object. It basically uses a template Excel file to construct itself. The Excel file contains a template column color for the results section, etc. and then the code basically just prints over those template columns, it doesn't actually customize the look of the file itself, only puts the data into it.
However, this is an issue because after it's done, our template accounts for the most POSSIBLE rows it can, but a lot of the times (most of the time), we use not even half of them.
What's the easiest way to remove all rows that DO NOT have cell data in them after the file has been created, working directly with the Microsoft.Office.Interop.Excel.Workbook object. We already have a "cleanup" method that runs after creation, but I want to add that logic to it. Here's our current cleanup:
private void CleanupExcel()
{
if (!_visible && _workbook != null)
{
_workbook.Close(false, Missing.Value, Missing.Value);
}
_workbook = null;
_sheet = null;
if (_excel != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(_excel);
// WW, 5/26/09: not sure if a problem here, but it probably is since the code was taken from here
// but in the indicator, Excel exists in the process even after the app is closed. The code here seems to fix it.
GC.Collect();
GC.WaitForPendingFinalizers();
}
_excel = null;
}
P.S. It's the first of two sheets in the document by the way. I also have access to the Microsoft.Office.Interop.Excel.Worksheet object if it's easier to do that way.
Assuming that all the empty rows are at the bottom of the sheets, you should be able to select them as a range and then delete them all, something like this I think:
Excel.Range range = _sheet.get_Range("A501", "A60000");
Excel.Range row = range.EntireRow;
rowDelete(Type.Missing);
If they're not at the bottom, maybe you could do a sort so that they all end up at the bottom and then use something similar to my code.
Try the following. It basically goes through a range (which I've hard-coded to be A1:A10), checks which rows are empty, marks them for deletion, then sweeps though and deletes them.
public void RemoveRows()
{
Excel.Range rng = Application.get_Range("A1", "A10");
List<int> rowsMarkedForDeletion = new List<int>();
for(int i = 0; i < rng.Rows.Count; i++)
{
if(Application.WorksheetFunction.CountA(rng[i + 1].EntireRow) == 0)
{
rowsMarkedForDeletion.Add(i + 1);
}
}
for(int i = rowsMarkedForDeletion.Count - 1; i >= 0; i--)
{
rng[rowsMarkedForDeletion[i]].EntireRow.Delete();
}
}
To give full credit, using COUNTA is a technique I learned from OzGrid.

Categories

Resources