从剪贴板读取数据到 DataTable 时保留空 Excel 单元格

Preserve empty Excel cells when reading data from clipboard into DataTable

我正在使用以下代码将剪贴板中的 Excel 数据读入 C# 数据 table。从 to 中找到的代码相对没有变化。然后,我将数据 table 作为数据源添加到 DataGridView 控件进行操作。

但是,在我的 Excel 数据中,我有 blank/empty 个单元格需要保留,而这段代码不会这样做(跳过空白单元格,有效地压缩每一行,不留空space;Excel XML) 中缺少空单元格。传输到数据时如何保留空单元格 table?

方法:

private DataTable ParseClipboardData(bool blnFirstRowHasHeader)
    {
        var clipboard = Clipboard.GetDataObject();
        if (!clipboard.GetDataPresent("XML Spreadsheet")) return null;
        StreamReader streamReader = new StreamReader((MemoryStream)clipboard.GetData("XML Spreadsheet"));
        streamReader.BaseStream.SetLength(streamReader.BaseStream.Length - 1);

        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.LoadXml(streamReader.ReadToEnd());
        XNamespace ssNs = "urn:schemas-microsoft-com:office:spreadsheet";
        DataTable dt = new DataTable();

        var linqRows = xmlDocument.fwToXDocument().Descendants(ssNs + "Row").ToList<XElement>();
        for (int x = 0; x < linqRows.Max(a => a.Descendants(ssNs + "Cell").Count()); x++)
            dt.Columns.Add("Column " + x.ToString());

        int intCol = 0;
        DataRow currentRow;

        linqRows.ForEach(rowElement =>
        {
            intCol = 0;
            currentRow = dt.Rows.Add();
            rowElement.Descendants(ssNs + "Cell")
                .ToList<XElement>()
                .ForEach(cell => currentRow[intCol++] = cell.Value);
        });

        if (blnFirstRowHasHeader)
        {
            int x = 0;
            foreach (DataColumn dcCurrent in dt.Columns)
                dcCurrent.ColumnName = dt.Rows[0][x++].ToString();

            dt.Rows.RemoveAt(0);
        }

        return dt;
    }

扩展方法:

public static XDocument fwToXDocument(this XmlDocument xmlDocument)
{
    using (XmlNodeReader xmlNodeReader = new XmlNodeReader(xmlDocument))
    {
        xmlNodeReader.MoveToContent();
        var doc = XDocument.Load(xmlNodeReader);
        return doc;
    }
}

举个例子来说明: (Excel 2015)

Excel 中的范围,已复制到剪贴板

Winform 上的 DataGridView,以数据 table 作为数据源

如果前一个单元格丢失(具有空值),则单元格的 xml 将具有索引属性。您可以更新代码以检查列索引是否已更改,然后再将其复制到数据 table 行。

linqRows.ForEach(rowElement =>
{
    intCol = 0;
    currentRow = dt.Rows.Add();
    rowElement.Descendants(ssNs + "Cell")
        .ToList<XElement>()                    
        .ForEach(cell => 
        {
            int cellIndex = 0;
            XAttribute indexAttribute = cell.Attribute(ssNs + "Index");

            if (indexAttribute != null)
            {
                Int32.TryParse(indexAttribute.Value, out cellIndex);
                intCol = cellIndex - 1;
            }

            currentRow[intCol] = cell.Value;
            intCol++;
        });
});