简体   繁体   English

在 OpenXML 和 SAX 中使用模板

[英]Using a template with OpenXML and SAX

I'm creating a large XLSX file from a datatable, using the SAX method proposed in Parsing and Reading Large Excel Files with the Open XML SDK .我正在从数据表创建一个大型 XLSX 文件,使用在Parsing and Reading Large Excel Files with the Open XML SDK 中提出的 SAX 方法。 I'm using an XLSX file as a template.我使用 XLSX 文件作为模板。

The method described in that post works fine to substitute a new sheet in for an existing one, but I want to copy the header row from the sheet in the template (string values, formatting, etc), instead of just using the header row from the datatable as the original code does.该帖子中描述的方法可以很好地替换现有工作表中的新工作表,但我想从模板中的工作表复制标题行(字符串值、格式等),而不是仅使用来自与原始代码一样的数据表。

I've tried the code below, but the XLSX file ends up with no text in the header row - the formatting is copied, just not the text.我已经尝试了下面的代码,但是 XLSX 文件的标题行中没有文本 - 格式被复制,而不是文本。 I've looked in the XML file for the sheet and it looks OK to me (referencing the sharedStrings.xml file, which still has the definition of the strings).我查看了工作表的 XML 文件,对我来说它看起来没问题(引用了 sharedStrings.xml 文件,它仍然具有字符串的定义)。 The reflected code from the Open XML SDK 2.0 Productivity Tool shows a slightly odd result though: the cells don't appear to have a text value set:来自Open XML SDK 2.0 Productivity Tool的反射代码显示了一个稍微奇怪的结果:单元格似乎没有设置文本值:

cellValue1.Text = "";

even though the XML says:即使 XML 说:

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

The main code used by the OpenXmlReader is below: 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();
        }
    }
}

The clue was that the Productivity Tool was showing blank values for the header cells on the generated sheet, and also that the validation formulae from the template were missing.线索是生产力工具在生成的工作表上显示标题单元格的空白值,并且模板中的验证公式丢失。 These are both text, which wasn't copied from the template sheet to the new sheet using the combination of OpenXmlReader.Read() and OpenXmlReader.WriteStartElement() .这些都是文本,没有使用OpenXmlReader.Read()OpenXmlReader.WriteStartElement()的组合从模板工作表复制到新工作表。

When the element is an OpenXmlLeafTextElement then the OpenXmlReader.GetText() method will return the text - this works for both text values in cells and for formulae.当元素是OpenXmlLeafTextElementOpenXmlReader.GetText()方法将返回文本 - 这适用于单元格中的文本值和公式。

The working code is shown below:工作代码如下所示:

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

        // write sheet element
        openXmlWriter.WriteStartElement(new SheetData());

        // read first row from template and copy into the new sheet
        openXmlReader.Read();

        do
        {
            if (openXmlReader.IsStartElement)
            {
                openXmlWriter.WriteStartElement(openXmlReader);
                
                // this bit is needed to get cell values
                if (openXmlReader.ElementType.IsSubclassOf(typeof(OpenXmlLeafTextElement)))
                {
                    openXmlWriter.WriteString(openXmlReader.GetText());
                }
            }
            else if (openXmlReader.IsEndElement)
            {
                openXmlWriter.WriteEndElement();
            }

            openXmlReader.Read();

        } while (!(openXmlReader.ElementType == typeof(Row) && openXmlReader.IsEndElement));

        openXmlWriter.WriteEndElement();

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

            openXmlWriter.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
                openXmlWriter.WriteElement(c);
            }

            // end row
            openXmlWriter.WriteEndElement();
        }

        // end sheet
        openXmlWriter.WriteEndElement();
    }
    else
    {
        if (openXmlReader.IsStartElement)
        {
            openXmlWriter.WriteStartElement(openXmlReader);

            // this bit is needed to get formulae and that kind of thing
            if (openXmlReader.ElementType.IsSubclassOf(typeof(OpenXmlLeafTextElement)))
            {
                openXmlWriter.WriteString(openXmlReader.GetText());
            }
        }
        else if (openXmlReader.IsEndElement)
        {
            openXmlWriter.WriteEndElement();
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM