Как указать формат для отдельных ячеек с Excel. Диапазон set_Value ()

Когда я пишу целую таблицу в рабочий лист Excel, я знаю для работы с целым Диапазоном сразу вместо того, чтобы писать в отдельные ячейки. Однако есть ли способ указать формат, поскольку я заполняю массив, который я собираюсь экспортировать в Excel?

Вот то, что я делаю теперь:

object MissingValue = System.Reflection.Missing.Value;
Excel.Application excel = new Excel.Application();
int rows = 5;
int cols = 5;
int someVal;

Excel.Worksheet sheet = (Excel.Worksheet)excel.Workbooks.Add(MissingValue).Sheets[1];
Excel.Range range = sheet.Range("A1", sheet.Cells(rows,cols));
object[,] rangeData = new object[rows,cols];
for(int r = 0; r < rows; r++)
{
    for(int c = 0; c < cols; c++)
    {
        someVal = r + c;
        rangeData[r,c] = someVal.ToString();
    }
}
range.set_Value(MissingValue, rangeData);

Теперь предположите, что я хочу, чтобы некоторые из тех чисел были отформатированы как проценты. Я знаю, что могу возвратиться на основе ячейки ячейкой и изменить форматирование, но это, кажется, побеждает целую цель использовать единственный Диапазон set_Value () вызов. Я могу сделать свой rangeData [] структура включают информацию о форматировании, так, чтобы, когда я называю set_Value (), ячейки были отформатированы в способе, которым я хочу их?

Для разъяснения я знаю, что могу установить формат для всего Excel. Объект диапазона. Тому, что я хочу, нужно было указать другой формат для каждой ячейки, указанной во внутреннем цикле.

7
задан Matt Ellen 8 July 2019 в 11:01
поделиться

3 ответа

Итак, вот лучшее «решение», которое я нашел до сих пор. Это не та нирванна, которую я искал, но она намного быстрее, чем установка формата для каждой ячейки в отдельности.

// 0-based indexes
static string RcToA1(int row, int col)
{
    string toRet = "";
    int mag = 0;
    while(col >= Math.Pow(26, mag+1)){mag++;}
    while (mag>0)
    {
        toRet += System.Convert.ToChar(64 + (byte)Math.Truncate((double)(col/(Math.Pow(26,mag)))));
        col -= (int)Math.Truncate((double)Math.Pow(26, mag--));
    }
    toRet += System.Convert.ToChar(65 + col);
    return toRet + (row + 1).ToString();
}

static Random rand = new Random(DateTime.Now.Millisecond);
static string RandomExcelFormat()
{
    switch ((int)Math.Round(rand.NextDouble(),0))
    {
        case 0: return "0.00%";
        default: return "0.00";
    }
}


struct ExcelFormatSpecifier
{
    public object NumberFormat;
    public string RangeAddress;
}

static void DoWork()
{
    List<ExcelFormatSpecifier> NumberFormatList = new List<ExcelFormatSpecifier>(0);

    object[,] rangeData = new object[rows,cols];
    for(int r = 0; r < rows; r++)
    {
        for(int c = 0; c < cols; c++)
        {
            someVal = r + c;
            rangeData[r,c] = someVal.ToString();
            NumberFormatList.Add(new ExcelFormatSpecifier
                {
                    NumberFormat = RandomExcelFormat(),
                    RangeAddress = RcToA1(rowIndex, colIndex)
                });
        }
    }
    range.set_Value(MissingValue, rangeData);

    int max_format = 50;
    foreach (string formatSpecifier in NumberFormatList.Select(p => p.NumberFormat).Distinct())
    {
        List<string> addresses = NumberFormatList.Where(p => p.NumberFormat == formatSpecifier).Select(p => p.RangeAddress).ToList();
        while (addresses.Count > 0)
        {
            string addressSpecifier = string.Join(",",     addresses.Take(max_format).ToArray());
            range.get_Range(addressSpecifier, MissingValue).NumberFormat = formatSpecifier;
            addresses = addresses.Skip(max_format).ToList();
        }
    }
}

В основном происходит то, что я храню список информации о формате для каждой ячейки в NumberFormatList (каждый элемент также содержит адрес в стиле A1 диапазона, к которому он применяется). Первоначальная идея заключалась в том, что для каждого отдельного формата на листе я должен иметь возможность создать Excel.Range только из этих ячеек и применить формат к этому диапазону за один вызов. Это уменьшит количество обращений к NumberFormat с (потенциально) тысяч до нескольких (сколько бы разных форматов у вас ни было).

Я столкнулся с проблемой, потому что вы, очевидно, не можете построить диапазон из произвольно длинного списка ячеек. После некоторого тестирования я обнаружил, что предел составляет от 50 до 100 ячеек, которые можно использовать для определения произвольного диапазона (например, range.get_Range ("A1, B1, C1, A2, AA5, .....") . Итак, как только я получил список всех ячеек, к которым нужно применить формат, у меня есть последний цикл while (), который применяет формат к 50 из этих ячеек за раз.

Это не идеально, но это по-прежнему сокращает количество обращений к NumberFormat в 50 раз, что является значительным. Создание моей электронной таблицы без какой-либо информации о формате (только с использованием range.set_Value ()) занимает около 3 секунд. Когда я применяю форматы, 50 ячеек в время, которое удлиняется примерно до 10. Когда я применяю информацию о формате индивидуально к каждой ячейке, создание таблицы занимает более 2 минут!

2
ответ дан 7 December 2019 в 14:31
поделиться

Вы можете применить форматирование к диапазону, а затем заполнить его значениями, которые вы не можете указать форматирование в вашем массиве object [,]

2
ответ дан 7 December 2019 в 14:31
поделиться

Вы не можете сделать это, потому что нет кодировки команд MIPS, которая поддерживает такую вещь. Вы должны сделать сложение самостоятельно:

add $a2, $a1, $t2
lw  $s2, 0($a2) 

Кодировка команды lw выглядит следующим образом:

1000 11ss ssst tttt iiii iiii iiii iiii

Где sssss - номер исходного регистра, ttttt - номер целевого регистра, а iiiiiiiiiiii - немедленный. В этом кодировании нет места (и нет альтернативных кодировок команд), которые используют два регистра для генерации адреса памяти. Конкретная машинная команда, которая будет закодирована из приведенного выше примера:

1000 1100 1101 0010 0000 0000 0000 0000

Поскольку непосредственный - 0 , $ s2 является регистром 18 и $ a2 является регистром 6 .

-121--2839466-

Я бы сказал, что это полностью зависит от заданных временных рамок. Если у вас есть время потратить почти в два раза больше времени, чем вы бы обычно требовали, тогда идите на это. Но на мой взгляд скорость - это в наши дни один из важнейших факторов (для конкурентоспособных компаний).

-121--1150847-

Форматирование применяется к каждой отдельной ячейке во внутреннем цикле с помощью

for(int r = 0; r < rows; r++)
{
    for(int c = 0; c < cols; c++)
    {
       Excel.Range r2 = sheet.Cells( r, c );
       r2.xxxx = "";
    }
}

После r2 можно изменить формат ячейки любым способом.

0
ответ дан 7 December 2019 в 14:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: