I've got this code, which should left-align the contents of a particular column:
Cell memberItemCodeCell = customerWorksheet.Cells[rowToPopulate, MEMBERITEMCODE_COL];
memberItemCodeCell.PutValue(frbdbc.MemberItemCode, true);
var micStyle = memberItemCodeCell.GetStyle();
micStyle.Font.Name = fontForSheets;
micStyle.Font.Size = 11;
micStyle.HorizontalAlignment = TextAlignmentType.Left;
micStyle.IsTextWrapped = false;
memberItemCodeCell.SetStyle(micStyle, flag);
It works ... sometimes:
Why in the heck would right-aligning sometimes happen?
Any value which could be seen as an int (contains no alpha chars or dashes) right-aligns; but why would it not respect the explicit left-aligning, regardless of whether or not it "looked like" an int?
There is some "general" formatting that applies to the entire row after all the column-specific code:
CellsFactory cf = new CellsFactory();
Style style4 = cf.CreateStyle();
if (shipVarDbl >= 1.0) // fewer were shipped than were ordered
{
style4.ForegroundColor = Color.LightGreen;
}
else if (shipVarDbl < 0.0) // more were shipped than were ordered
{
style4.ForegroundColor = Color.PaleVioletRed;
}
style4.Font.Name = fontForSheets;
style4.Font.Size = 11;
style4.Pattern = BackgroundType.Solid;
rowRange.SetStyle(style4);
...but that shouldn't affect the aligning.
After the code shown first above runs as part of the PopulateCustomerSheet() method:
private void PopulateCustomerSheet()
{
try
{
if (null == _fillRateByDistributorByCustomerList) return;
foreach (FillRateByDistributorByCustomer frbdbc in _fillRateByDistributorByCustomerList)
{
AddCustomerRow(frbdbc);
}
AutoFitterOptions options = new AutoFitterOptions { OnlyAuto = true };
customerWorksheet.AutoFitColumns(options);
}
catch (Exception ex)
{
RoboReporterConstsAndUtils.HandleException(ex);
}
}
...it is borderized, configured for printing, and finally the sheet is written to disk:
BorderizeDataPortionOfCustomerSheet();
ConfigureCustomerSheetForPrinting();
// Write the file to disk
string fromAsYYYYMMDD = DateTime.Now.ToString("yyyy-MM-dd_hh-mm-ss");
RoboReporterConstsAndUtils.SetUniqueFolder(_unit);
String _uniqueFolder = RoboReporterConstsAndUtils.uniqueFolder;
var sharedFolder = String.Format(@"\\storageblade\cs\REPORTING\RoboReporter\{0}", _uniqueFolder);
RoboReporterConstsAndUtils.ConditionallyCreateDirectory(sharedFolder);
var filename = String.Format(@"{0}\{1} - Fill Rate - {2}.xlsx", sharedFolder, _unit, fromAsYYYYMMDD);
if (File.Exists(filename))
{
File.Delete(filename);
}
workBook.Save(filename, SaveFormat.Xlsx);
I can't imagine the borderizing or print configuring changing the alignment of a particular column on the sheet, but just in case that's possible, here are those methods:
private void BorderizeDataPortionOfCustomerSheet()
{
int rowsUsed = customerWorksheet.Cells.Rows.Count;
int colsUsed = SHIPVARIANCE_COL;
string bottomRightRange = string.Format("P{0}", rowsUsed);
var range = customerWorksheet.Cells.CreateRange("A1", bottomRightRange);
//Setting border for each cell in the range
var style = workBook.CreateStyle();
style.SetBorder(BorderType.BottomBorder, CellBorderType.Thin, Color.Black);
style.SetBorder(BorderType.LeftBorder, CellBorderType.Thin, Color.Black);
style.SetBorder(BorderType.RightBorder, CellBorderType.Thin, Color.Black);
style.SetBorder(BorderType.TopBorder, CellBorderType.Thin, Color.Black);
for (int r = range.FirstRow; r < range.RowCount; r++)
{
for (int c = range.FirstColumn; c < range.ColumnCount; c++)
{
Cell cell = customerWorksheet.Cells[r, c];
cell.SetStyle(style, new StyleFlag()
{
TopBorder = true,
BottomBorder = true,
LeftBorder = true,
RightBorder = true
});
}
}
//Setting outline border to range
range.SetOutlineBorder(BorderType.TopBorder, CellBorderType.Thin, Color.Black);
range.SetOutlineBorder(BorderType.BottomBorder, CellBorderType.Thin, Color.Black);
range.SetOutlineBorder(BorderType.LeftBorder, CellBorderType.Thin, Color.Black);
range.SetOutlineBorder(BorderType.RightBorder, CellBorderType.Thin, Color.Black);
customerWorksheet.FreezePanes(FIRST_DATA_ROW, SHORTNAME_COL, rowsUsed, colsUsed);
}
private void ConfigureCustomerSheetForPrinting()
{
const double INCHES_TO_CENTIMETERS_FACTOR = 2.54;
string lastColumn = GetExcelTextColumnName(customerWorksheet.Cells.Columns.Count);
string printArea = String.Format("A1:{0}{1}", lastColumn, customerWorksheet.Cells.Rows.Count);
customerWorksheet.PageSetup.PrintArea = printArea;
customerWorksheet.PageSetup.Orientation = PageOrientationType.Landscape;
// I don't know if this does anything; I would like to set it to 54%...
customerWorksheet.PageSetup.IsPercentScale = true;
customerWorksheet.PageSetup.FitToPagesWide = 1;
customerWorksheet.PageSetup.FitToPagesTall = 0;
customerWorksheet.PageSetup.LeftMargin = 0.5 * INCHES_TO_CENTIMETERS_FACTOR;
customerWorksheet.PageSetup.RightMargin = 0.5 * INCHES_TO_CENTIMETERS_FACTOR;
customerWorksheet.PageSetup.TopMargin = 0.5 * INCHES_TO_CENTIMETERS_FACTOR;
customerWorksheet.PageSetup.BottomMargin = 0.5 * INCHES_TO_CENTIMETERS_FACTOR;
customerWorksheet.PageSetup.HeaderMargin = 0;
customerWorksheet.PageSetup.FooterMargin = 0;
// Repeat rows
string repeatableRowRange = "$1:$1";
customerWorksheet.PageSetup.PrintTitleRows = repeatableRowRange;
}
How could this cause the column alignment to disrespect, disobey, and ignore the clear and present directive to left-align its contents?
UPDATE
Based on what I understood of the answer, I changed this:
rowRange.SetStyle(style4);
...to this:
var flag = new StyleFlag
{
CellShading = true,
FontName = true,
FontSize = true,
FontColor = true,
FontBold = true,
NumberFormat = true
};
rowRange.ApplyStyle(style4, flag);
...but it made no difference.
UPDATE 2
This is the code that explicitly sets the problem column:
Cell memberItemCodeCell = customerWorksheet.Cells[rowToPopulate, MEMBERITEMCODE_COL];
memberItemCodeCell.PutValue(frbdbc.MemberItemCode, true);
var micStyle = memberItemCodeCell.GetStyle();
micStyle.Font.Name = fontForSheets;
micStyle.Font.Size = 11;
micStyle.HorizontalAlignment = TextAlignmentType.Left;
micStyle.IsTextWrapped = false;
memberItemCodeCell.SetStyle(micStyle, flag);
So I'm not using a Range here, but a cell. Should I use a range, so that I can use ApplyStyle()? I tried doing that, but it doesn't seem to want to accept PutValue(), etc.
Besides, the value supplied (frbdbc.MemberItemCode) is a string, so shouldn't this prevent Excel from treating it like an int? What else must I do to let Excel know, "Hey, this is a string, just present it as-is."
UPDATE 3
I tried this code that was sent me by Aspose:
customerWorksheet.Cells.CreateRange(rangeBegin, rangeEnd).ApplyStyle(style4, new StyleFlag() { Font = true, CellShading = true });
In context:
string rangeBegin = RoboReporterConstsAndUtils.GetRangeLettersNumbersAsStr(SHORTNAME_COL + 1, rowToPopulate);
string rangeEnd = RoboReporterConstsAndUtils.GetRangeLettersNumbersAsStr(SHIPVARIANCE_COL + 1, rowToPopulate);
CellsFactory cf = new CellsFactory();
Style style4 = cf.CreateStyle();
if (shipVarDbl >= 1.0) // fewer were shipped than were ordered
{
style4.ForegroundColor = Color.LightGreen;
}
else if (shipVarDbl < 0.0) // more were shipped than were ordered
{
style4.ForegroundColor = Color.PaleVioletRed;
}
style4.Font.Name = fontForSheets;
style4.Font.Size = 11;
style4.Pattern = BackgroundType.Solid;
customerWorksheet.Cells.CreateRange(rangeBegin, rangeEnd).ApplyStyle(style4, new StyleFlag() { Font = true, CellShading = true });
...and it still makes no difference.
UPDATE 4
I thought this might work, which I found here:
micStyle.NumberFormat = 2;
(replacing the "2" with whatever number reprsents "Text"); but "NumberFormat" is not recognized. Is that an obsolete example?
UPDATE 5
Okay, there must be some logical reason why this is [not] happening. Here are the manipulations I make to that column, in order:
First, the header row is written:
private static readonly int MEMBERITEMCODE_COL = 4;
. . .
private void AddCustomerSheetHeaderRow()
{
var flag = new StyleFlag
{
CellShading = true,
FontName = true,
FontSize = true,
FontColor = true,
FontBold = true,
NumberFormat = true
};
. . .
CellsFactory cfMemberItemCode = new CellsFactory();
Cell MemberItemCodeCell = customerWorksheet.Cells[0, MEMBERITEMCODE_COL];
MemberItemCodeCell.PutValue("Member Item Code");
var styleMemberItemCode = cfMemberItemCode.CreateStyle();
styleMemberItemCode.HorizontalAlignment = TextAlignmentType.Left;
styleMemberItemCode.Font.Name = fontForSheets;
styleMemberItemCode.Font.IsBold = true;
styleMemberItemCode.Font.Size = 11;
styleMemberItemCode.ForegroundColor = Color.LightBlue;
styleMemberItemCode.Pattern = BackgroundType.Solid;
MemberItemCodeCell.SetStyle(styleMemberItemCode, flag);
. . .
}
So I align the column on the header row; it is index 4, IOW column "E"
Next, AddCustomerRow() is called multiple times, populating the "data" portion of the sheet (everything below the header row):
private void AddCustomerRow(FillRateByDistributorByCustomer frbdbc)
{
var flag = new StyleFlag
{
CellShading = true,
FontName = true,
FontSize = true,
FontColor = true,
FontBold = true,
NumberFormat = true
};
. . .
// This is sometimes seen as an int by Excel, and sports the green warning triangle
// Fixed that with the second (true) arg to PutValue(), but it right-aligns int-like vals...?!@?
Cell memberItemCodeCell = customerWorksheet.Cells[rowToPopulate, MEMBERITEMCODE_COL];
memberItemCodeCell.PutValue(frbdbc.MemberItemCode, true);
var micStyle = memberItemCodeCell.GetStyle();
micStyle.Font.Name = fontForSheets;
micStyle.Font.Size = 11;
micStyle.HorizontalAlignment = TextAlignmentType.Left;
micStyle.IsTextWrapped = false;
memberItemCodeCell.SetStyle(micStyle, flag);
. . .
string rangeBegin = RoboReporterConstsAndUtils.GetRangeLettersNumbersAsStr(SHORTNAME_COL + 1, rowToPopulate);
string rangeEnd = RoboReporterConstsAndUtils.GetRangeLettersNumbersAsStr(SHIPVARIANCE_COL + 1, rowToPopulate);
CellsFactory cf = new CellsFactory();
Style style4 = cf.CreateStyle();
if (shipVarDbl >= 1.0) // fewer were shipped than were ordered
{
style4.ForegroundColor = Color.LightGreen;
}
else if (shipVarDbl < 0.0) // more were shipped than were ordered
{
style4.ForegroundColor = Color.PaleVioletRed;
}
style4.Pattern = BackgroundType.Solid;
style4.Font.Name = fontForSheets;
style4.Font.Size = 11;
customerWorksheet.Cells.CreateRange(rangeBegin
|rangeEnd).ApplyStyle(style4, new StyleFlag() { Font = true,
CellShading = true });
}
Here, too, the alignment is set to left. After setting up each column, a "general purpose row style" is created, to conditionally color the entire row. That works fine - the appropriate rows are colorized.
Then, because the colorizing of the header row doesn't work as tried previously (setting it to LightBlue doesn't work), I do it after the face like so:
private void RecolorizeTopRowOfCustomerSheet()
{
. . .
CellsFactory cfMemberItemCode = new CellsFactory();
Cell MemberItemCodeCell = customerWorksheet.Cells[0,
MEMBERITEMCODE_COL];
var styleMemberItemCode = cfMemberItemCode.CreateStyle();
styleMemberItemCode.HorizontalAlignment = TextAlignmentType.Left;
styleMemberItemCode.Font.Name = fontForSheets;
styleMemberItemCode.Font.IsBold = true;
styleMemberItemCode.Font.Size = 11;
styleMemberItemCode.ForegroundColor = Color.LightBlue;
styleMemberItemCode.Pattern = BackgroundType.Solid;
MemberItemCodeCell.SetStyle(styleMemberItemCode);
. . .
// Give it borders
Range _range;
_range = customerWorksheet.Cells.CreateRange("A1", "P1");
//Set the borders with hair lines style.
_range.SetOutlineBorders(CellBorderType.Hair, Color.Black);
}
...Borders are also added to that row. Finally, borders are added to the data rows (everything past row 1):
private void BorderizeDataPortionOfCustomerSheet()
{
int rowsUsed = customerWorksheet.Cells.Rows.Count;
int colsUsed = SHIPVARIANCE_COL;
string bottomRightRange = string.Format("P{0}", rowsUsed);
var range = customerWorksheet.Cells.CreateRange("A1", bottomRightRange);
//Setting border for each cell in the range
var style = workBook.CreateStyle();
style.SetBorder(BorderType.BottomBorder, CellBorderType.Thin, Color.Black);
style.SetBorder(BorderType.LeftBorder, CellBorderType.Thin, Color.Black);
style.SetBorder(BorderType.RightBorder, CellBorderType.Thin, Color.Black);
style.SetBorder(BorderType.TopBorder, CellBorderType.Thin, Color.Black);
for (int r = range.FirstRow; r < range.RowCount; r++)
{
for (int c = range.FirstColumn; c < range.ColumnCount; c++)
{
Cell cell = customerWorksheet.Cells[r, c];
cell.SetStyle(style, new StyleFlag()
{
TopBorder = true,
BottomBorder = true,
LeftBorder = true,
RightBorder = true
});
}
}
//Setting outline border to range
range.SetOutlineBorder(BorderType.TopBorder, CellBorderType.Thin, Color.Black);
range.SetOutlineBorder(BorderType.BottomBorder, CellBorderType.Thin, Color.Black);
range.SetOutlineBorder(BorderType.LeftBorder, CellBorderType.Thin, Color.Black);
range.SetOutlineBorder(BorderType.RightBorder, CellBorderType.Thin, Color.Black);
customerWorksheet.FreezePanes(FIRST_DATA_ROW, SHORTNAME_COL, rowsUsed, colsUsed);
}
Then the file is saved to disk - with a mishmash of some items in the MemberItemCode colum left-aligned and others right-aligned. Why isn't there some call like:
Column[3].Alignment = AlignLeft;
...that would easily align everything in a particular column as desired; or is there? Since what I'm trying either doesn't work or is very temperamental, something like that would certainly be handy.