使用OpenXML和SAX模板

6
我正在使用Parsing and Reading Large Excel Files with the Open XML SDK提出的SAX方法,从datatable创建一个大型XLSX文件。我正在使用一个XLSX文件作为模板。那篇文章中描述的方法可以将新工作表替换为现有工作表,但是我想复制模板中工作表的标题行(包括字符串值、格式等),而不仅仅使用datatable的标题行,如原始代码所示。
我尝试了下面的代码,但生成的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();
        }
    }
}

这真的可以处理所有数据类型吗(数字、布尔值、共享字符串、日期、时间跨度)?“c.DataType = CellValues.String;” - swcraft
1个回答

9
线索是生产力工具在生成的表格中显示标题单元格的空白值,以及模板中的验证公式缺失。这两者都是文本,使用 OpenXmlReader.Read()OpenXmlReader.WriteStartElement() 的组合没有从模板表格复制到新表格中。
当元素是 OpenXmlLeafTextElement 时,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();
        }
    }
}

1
写入器对象是什么? - Satish Kumar sonker
作者是一个OpenXmlWriter - 我已经更改了变量名称以使其更清晰 - Jonathan Sayce

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接