Почему содержимое ячейки выравнивается по левому краю, а иногда выравнивается по правому краю (Aspose Cells)?

У меня есть этот код, который должен выравнивать содержимое определенного столбца по левому краю:

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;

... это легко выровняет все в определенном столбце по желанию; или есть? Поскольку то, что я пробую, либо не работает, либо очень темпераментно, что-то подобное, безусловно, было бы удобно.


person B. Clay Shannon    schedule 16.01.2017    source источник


Ответы (2)


Я считаю, что указанная проблема вызвана тем, что вы перезаписываете все аспекты стиля объектом, созданным с нуля. Обратите внимание, что когда вы применяете стиль к ячейке, вы сначала получаете стиль из этой ячейки, что позволяет сохранить примененный к ней числовой формат. Однако, когда вы создаете объект Style с нуля и применяете стиль к диапазону при использовании Range.SetStyle, каждый аспект вновь созданного объекта Style перезаписывается в диапазон, что приводит к изменению формата на Общий для каждой ячейки в диапазон. Вместо этого я предлагаю вам использовать метод Range.ApplyStyle, который позволяет передать экземпляр StyleFlag вышеупомянутому методу. Таким образом, вы можете контролировать аспекты объекта Style, которые вы хотите перезаписать.

Примечание. Я работаю разработчиком-евангелистом в Aspose.

person Prorata    schedule 17.01.2017
comment
Можете ли вы привести пример того, как именно это сделать? В частности, как должен выглядеть флаг? У меня есть rowRange.ApplyStyle(style4, ). - person B. Clay Shannon; 17.01.2017
comment
Пожалуйста, смотрите мое обновление - моя попытка следовать вашему предложению не имела значения. - person B. Clay Shannon; 17.01.2017
comment
Я не совсем понимаю ваш ответ; в обновлении 5 я выкладываю все, что я делаю с этой колонкой, в порядке выполнения. Что еще необходимо для предотвращения выравнивания некоторых значений по правому краю? Это не должно быть таким запутанным. - person B. Clay Shannon; 18.01.2017
comment
Мои комментарии основаны на том факте, что формат ваших ячеек меняется на Общий, что также вызывает сдвиг выравнивания для числовых значений. Если вы применяете стиль, который был создан с нуля, числовой формат такого стиля автоматически устанавливается на Общий, поэтому числовой формат всех ячеек в диапазоне будет соответствующим образом изменен. Тем не менее, я подозреваю, что ваш код где-то перезаписывает стили. Для дальнейшего расследования этого вопроса я смиренно прошу вас продолжить общение на форуме поддержки Aspose.Cells, предоставив простой образец заявления. - person Prorata; 18.01.2017
comment
Изучив обновление 5 из описания проблемы, я заметил, что вы устанавливаете для StyleFlag.Number значение true в методе AddCustomerSheetHeaderRow. Не могли бы вы попробовать случай, прокомментировав это утверждение? - person Prorata; 18.01.2017
comment
Хорошо, спасибо, я попробую ваше последнее предложение, но разве это не должно повлиять только на эту одну строку?; в своем комментарии до этого вы говорите, что мой формат меняется на общий. Где это происходит? - person B. Clay Shannon; 18.01.2017
comment
Я закомментировал NumberFormat = true как из упомянутого вами однострочного метода, так и из объявления флага AddCustomerRow(), и это не имеет значения - я все еще получаю комбинацию значений, выровненных по левому и правому краю в элементе-члене Кодовая колонка. - person B. Clay Shannon; 18.01.2017
comment
Обратите внимание, что закомментирование NumberFormat = true гарантирует, что любые настройки, связанные с числовым форматом, не будут перезаписаны. К сожалению, это не устранило основную проблему. - person Prorata; 19.01.2017
comment
Если вы проверите свою ветку на форуме поддержки Aspose.Cells по той же теме, вы заметите, что я поделился фрагментом кода, а также электронными таблицами ввода и вывода для вашей справки. Если вы проверите output.xlsx, вы заметите, что ячейка F3 сохранила выравнивание с использованием предоставленного фрагмента, однако, если вы замените Range.ApplyStyle на Range.SetStyle, выравнивание изменится. Это связано с тем, что метод Range.ApplyStyle не перезаписывает все аспекты стиля. Ссылка: aspose.com/community/forums/permalink/ 820347/820375/ - person Prorata; 19.01.2017
comment
Обратите внимание, что не всегда возможно точно определить причину проблемы без просмотра фактического потока приложения и входной электронной таблицы, поэтому я снова прошу вас поделиться простым исполняемым образцом приложения вместе с источником и назначением (желаемые результаты) в Форум поддержки Aspose.Cells для дальнейшего расследования. - person Prorata; 19.01.2017
comment
У меня получилось, спасибо. Смотрите мой автоответ - мне пришлось переборщить, что не оптимально, но работает, так что больше не буду об этом беспокоиться. - person B. Clay Shannon; 19.01.2017
comment
Приятно осознавать, что тебе удалось достичь цели. Если вы можете, опубликуйте свой образец приложения на форуме поддержки Aspose.Cells, чтобы мы могли просмотреть его и предложить улучшения. - person Prorata; 23.01.2017
comment
Спасибо; Я уже разместил там весь код из этого класса, кроме того, что в ответе ниже. - person B. Clay Shannon; 23.01.2017

Единственный способ, которым я мог заставить это работать, - это "грубая сила", явно установив для всех ячеек в этом столбце выравнивание по левому краю после того, как все остальное было сделано:

private static readonly int MEMBERITEMCODE_COL = 4;
. . .
SetAllCustomerSheetColValsLeftAligned(MEMBERITEMCODE_COL);
BorderizeDataPortionOfCustomerSheet();    
. . .    
private void SetAllCustomerSheetColValsLeftAligned(int colIndex)
{
    int rowsUsed = customerWorksheet.Cells.Rows.Count;
    CellsFactory cf = new CellsFactory();
    Cell currentCell = null;
    Style currentStyle = null;
    for (int i = 2; i <= rowsUsed; i++)
    {
        currentCell = customerWorksheet.Cells[i, colIndex];
        currentStyle = cf.CreateStyle();
        currentStyle.HorizontalAlignment = TextAlignmentType.Left;
        currentStyle.Font.Name = fontForSheets;
        currentStyle.Font.Size = 11;
        currentCell.SetStyle(currentStyle);
    }
}
person B. Clay Shannon    schedule 18.01.2017