Использование шаблона с OpenXML и SAX - PullRequest
4 голосов
/ 04 октября 2011

Я создаю большой файл XLSX из таблицы данных, используя метод SAX, предложенный в Анализ и чтение больших файлов Excel с помощью Open XML SDK . Я использую файл XLSX в качестве шаблона.

Метод, описанный в этом посте, прекрасно работает для замены нового листа на существующий, но я хочу скопировать строку заголовка из листа в шаблоне (строковые значения, форматирование и т. Д.) Вместо простого использования строка заголовка из таблицы данных, как это делает исходный код.

Я попробовал приведенный ниже код, но файл XLSX заканчивается без текста в строке заголовка - форматирование копируется, но не текст. Я посмотрел в XML-файле для листа, и он выглядит хорошо для меня (ссылаясь на файл sharedStrings.xml, который по-прежнему имеет определение строк). Отраженный код из Open XML SDK 2.0 Productivity Tool показывает немного странный результат: ячейки не имеют установленного текстового значения:

cellValue1.Text = "";

хотя в XML сказано:

<x:c r="A1" s="4" t="s">

Основной код, используемый OpenXmlReader, приведен ниже:

while (reader.Read())
{
    if (reader.ElementType == typeof(SheetData))
    {
        if (reader.IsEndElement)
            continue;

        // Write sheet element
        writer.WriteStartElement(new SheetData());

        // copy header row from template
        reader.Read();
        do
        {
            if (reader.IsStartElement)
            {
                writer.WriteStartElement(reader);
                        }
            else if (reader.IsEndElement)
            {
                writer.WriteEndElement();
            }
            reader.Read();
        } while (!(reader.ElementType == typeof(Row) && reader.IsEndElement));
        writer.WriteEndElement();

        // Write data rows
        foreach (DataRow dataRow in resultsTable.Rows)
        {
            // Write row element
            Row r = new Row();
            writer.WriteStartElement(r);

            foreach (DataColumn dataCol in resultsTable.Columns)
            {
                Cell c = new Cell();
                c.DataType = CellValues.String;
                CellValue v = new CellValue(dataRow[dataCol].ToString());
                c.Append(v);

                // Write cell element
                writer.WriteElement(c);
            }

            // End row
            writer.WriteEndElement();
        }

        // End sheet
        writer.WriteEndElement();
    }
    else
    {
        if (reader.IsStartElement)
        {
            writer.WriteStartElement(reader);
        }
        else if (reader.IsEndElement)
        {
            writer.WriteEndElement();
        }
    }
}

1 Ответ

7 голосов
/ 05 октября 2011

Подсказка заключалась в том, что Инструмент повышения производительности отображал пустые значения для ячеек заголовка на сгенерированном листе, а также что отсутствовали формулы проверки из шаблона. Это оба текста, которые не были скопированы с листа шаблона на новый лист с использованием комбинации OpenXmlReader.Read() и OpenXmlReader.WriteStartElement().

Если элемент является OpenXmlLeafTextElement, то метод OpenXmlReader.GetText() вернет текст - это работает как для текстовых значений в ячейках, так и для формул.

Рабочий код показан ниже:

while (reader.Read())
{
    if (reader.ElementType == typeof(SheetData))
    {
        if (reader.IsEndElement)
            continue;

        // Write sheet element
        writer.WriteStartElement(new SheetData());

        // read first row from template and copy into the new sheet
        reader.Read();
        do
        {
          if (reader.IsStartElement)
            {
                writer.WriteStartElement(reader);

                // this bit is needed to get cell values
                if (reader.ElementType.IsSubclassOf(typeof(OpenXmlLeafTextElement)))
                {
                    writer.WriteString(reader.GetText());
                }
            }
            else if (reader.IsEndElement)
            {
                writer.WriteEndElement();
            }
            reader.Read();
        } while (!(reader.ElementType == typeof(Row) && reader.IsEndElement));
        writer.WriteEndElement();

        // Write data rows
        foreach (DataRow dataRow in resultsTable.Rows)
        {
            // Write row element
            Row r = new Row();
            writer.WriteStartElement(r);

            foreach (DataColumn dataCol in resultsTable.Columns)
            {
                Cell c = new Cell();
                c.DataType = CellValues.String;
                CellValue v = new CellValue(dataRow[dataCol].ToString());
                c.Append(v);

                // Write cell element
                writer.WriteElement(c);
            }

            // End row
            writer.WriteEndElement();
        }

        // End sheet
        writer.WriteEndElement();
    }
    else
    {
        if (reader.IsStartElement)
        {
            writer.WriteStartElement(reader);
            // this bit is needed to get formulae and that kind of thing
            if (reader.ElementType.IsSubclassOf(typeof(OpenXmlLeafTextElement)))
            {
                writer.WriteString(reader.GetText());
            }
        }
        else if (reader.IsEndElement)
        {
            writer.WriteEndElement();
        }
    }
}
...