将模板与 OpenXML 和 SAX 结合使用

发布于 2024-12-08 06:51:41 字数 2397 浏览 0 评论 0原文

我正在使用 使用 Open XML SDK 解析和读取大型 Excel 文件。我使用 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();
        }
    }
}

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. I'm using an XLSX file as a template.

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. 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). 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:

cellValue1.Text = "";

even though the XML says:

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

The main code used by the OpenXmlReader is below:

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();
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

国粹 2024-12-15 06:51:41

线索是生产力工具在生成的工作表上显示标题单元格的空白值,并且模板中的验证公式也丢失。这些都是文本,未使用 OpenXmlReader.Read()OpenXmlReader.WriteStartElement() 组合从模板工作表复制到新工作表。

当元素是 OpenXmlLeafTextElement< /a> 然后 OpenXmlReader.GetText() 方法将返回文本 - 这适用于单元格中的文本值和公式。

工作代码如下所示:

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();
        }
    }
}

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().

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.

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();
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文