У меня есть этот код, который должен выравнивать содержимое определенного столбца по левому краю:
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);
Это работает... иногда:
Почему, черт возьми, иногда происходит выравнивание по правому краю?
Любое значение, которое можно рассматривать как целое (не содержащее альфа-символов или дефисов), выравнивается по правому краю; но почему бы ему не соблюдать явное выравнивание по левому краю, независимо от того, «похоже» ли оно на int?
Существует некоторое «общее» форматирование, которое применяется ко всей строке после всего кода, специфичного для столбца:
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);
... но это не должно влиять на выравнивание.
После того, как код, показанный выше, запускается как часть метода PopulateCustomerSheet():
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);
}
}
...обрамляется, настраивается на печать и, наконец, лист записывается на диск:
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);
Я не могу представить себе настройку границ или печати для изменения выравнивания определенного столбца на листе, но на всякий случай это возможно, вот эти методы:
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;
}
Как это могло привести к тому, что выравнивание столбца не уважало, не подчинялось и игнорировало директиву clear and present о выравнивании его содержимого по левому краю?
ОБНОВИТЬ
Основываясь на том, что я понял из ответа, я изменил это:
rowRange.SetStyle(style4);
...к этому:
var flag = new StyleFlag
{
CellShading = true,
FontName = true,
FontSize = true,
FontColor = true,
FontBold = true,
NumberFormat = true
};
rowRange.ApplyStyle(style4, flag);
... но это не имело значения.
ОБНОВЛЕНИЕ 2
Это код, который явно устанавливает проблемный столбец:
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);
Поэтому я использую здесь не диапазон, а ячейку. Должен ли я использовать диапазон, чтобы я мог использовать ApplyStyle()? Я пытался это сделать, но, похоже, он не хочет принимать PutValue() и т.д.
Кроме того, предоставленное значение (frbdbc.MemberItemCode) является строкой, поэтому не должно ли это препятствовать тому, чтобы Excel рассматривал его как целое число? Что еще я должен сделать, чтобы Excel знал: «Эй, это строка, просто представьте ее как есть».
ОБНОВЛЕНИЕ 3
Я попробовал этот код, который был отправлен мне Aspose:
customerWorksheet.Cells.CreateRange(rangeBegin, rangeEnd).ApplyStyle(style4, new StyleFlag() { Font = true, CellShading = true });
В контексте:
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 });
... и это все еще не имеет значения.
ОБНОВЛЕНИЕ 4
Я подумал, что это может сработать, и нашел здесь :
micStyle.NumberFormat = 2;
(заменив «2» любым числом, представляющим «Текст»); но "NumberFormat" не распознается. Это устаревший пример?
ОБНОВЛЕНИЕ 5
Хорошо, должна быть какая-то логическая причина, почему этого [не] происходит. Вот манипуляции, которые я делаю с этим столбцом, по порядку:
Сначала записывается строка заголовка:
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);
. . .
}
Поэтому я выравниваю столбец по строке заголовка; это индекс 4, столбец IOW "E"
Затем AddCustomerRow() вызывается несколько раз, заполняя часть листа «данные» (все ниже строки заголовка):
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 });
}
Здесь тоже выравнивание установлено по левому краю. После настройки каждого столбца создается «стиль строки общего назначения» для условного окрашивания всей строки. Это работает нормально - соответствующие строки раскрашены.
Затем, поскольку раскрашивание строки заголовка не работает, как пробовалось ранее (установка LightBlue не работает), я делаю это после лица следующим образом:
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);
}
... В эту строку также добавляются границы. Наконец, к строкам данных добавляются границы (все после строки 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);
}
Затем файл сохраняется на диск с мешаниной некоторых элементов в столбце MemberItemCode, выровненных по левому краю, и других, выровненных по правому краю. Почему нет такого вызова, как:
Column[3].Alignment = AlignLeft;
... это легко выровняет все в определенном столбце по желанию; или есть? Поскольку то, что я пробую, либо не работает, либо очень темпераментно, что-то подобное, безусловно, было бы удобно.