除非分隔符被转义,否则使用分隔符拆分

时间:2010-12-09 21:14:41

标签: c# excel string clipboard

我正在使用

读取来自excel的剪贴板数据

var stream = (System.IO.Stream) ( Forms.Clipboard.GetDataObject() ).GetData( Forms.DataFormats.CommaSeparatedValue );

但不幸的是,excel传递的是单元格文本而不是单元格值。当单元格使用特殊格式(例如千位分隔符)时,列中的一系列单元格的剪贴板数据如下所示:

 1,234,123.00    2,345.00    342.00      12,345.00

存储为:

\" 1,234,123.00 \",\" 2,345.00 \", 342.00 ,\" 12,345.00 \"

当我真正想要的是这个时候:

 1234123.00, 2345.00, 342.00, 12345.00

我之前使用clipData.Split(new string[] { "," }, StringSllitOptions.None))函数将我的CSV剪贴板数据转换为一系列单元格,但是当存在包含逗号的转义格式文本时,这会失败。


我问是否有人能想出将这个字符串拆分成一组单元格的方法,忽略在\"位内转义的逗号,因为这是Excel选择转义包含逗号的单元格的方式。

简而言之,我如何转换包含此字符串的单个字符串:

\" 1,234,123.00 \",\" 2,345.00 \", 342.00 ,\" 12,345.00 \"

进入包含以下内容的字符串数组:

{ "1,234,123.00", "2,345.00", "342.00", "12,345.00" }

不会破坏我解析一个简单的逗号分隔字符串的能力。

***** ***编辑

在此处跟进问题(表述为DFA):Split a string based on each time a Deterministic Finite Automata reaches a final state?

5 个答案:

答案 0 :(得分:3)

首先,我之前处理过Excel中的数据,您通常看到的是逗号分隔值,如果该值被视为字符串,则它将包含双引号(并且可以包含逗号和双引号)。如果它被认为是数字,则没有双引号。此外,如果数据包含双引号,则会用""这样的双引号分隔。所以假设所有这些都是我过去处理过这个问题的方法

public static IEnumerable<string> SplitExcelRow(this string value)
{
    value = value.Replace("\"\"", "&quot;");
    bool quoted = false;
    int currStartIndex = 0;
    for (int i = 0; i < value.Length; i++)
    {
        char currChar = value[i];
        if (currChar == '"')
        {
            quoted = !quoted;       
        }
        else if (currChar == ',')
        {
            if (!quoted)
            {
                yield return value.Substring(currStartIndex, i - currStartIndex)
                    .Trim()
                    .Replace("\"","")
                    .Replace("&quot;","\"");
                currStartIndex = i + 1;
            }
        }
    }
    yield return value.Substring(currStartIndex, value.Length - currStartIndex)
        .Trim()
        .Replace("\"", "")
        .Replace("&quot;", "\"");
}

当然这假设进入的数据是有效的,所以如果你有类似"fo,o"b,ar","bar""foo"这样的东西,这将无效。此外,如果您的数据包含&quot;,那么它将变为“可能或可能不合适的数据。”

答案 1 :(得分:1)

有很多方法可以做到这一点。一种不起眼的方法是:

  1. 将\“,\”转换为制表符或其他一些分隔符(我假设您在示例中遗漏了一些\“,否则字符串不一致
  2. 删除所有剩余的逗号
  3. 剥去所有剩余的\“
  4. 将分隔符(例如制表符)转换回逗号
  5. 现在你有了第一个想要的东西

答案 2 :(得分:1)

我同意Kyle关于你的字符串可能不一致。

而不是凯尔的第一步,你可以使用

string[] vals = Regex.Split(value, @"\s*\"",\s*");

答案 3 :(得分:0)

从您的输入示例中,我们可以看到有三个“不需要的”字符序列:

\"
\",
,\"

因此,将所有这些序列添加到Split方法的输入数组中:

string[] result = clipData.Split(new[] { @",\""", @"\"",", @"\""" }, 
    StringSplitOptions.None);

这将为您提供一个包含一些空元素的数组。如果这是一个问题,请使用StringSplitOptions.RemoveEmptyEntries代替StringSplitOptions.None

string[] result = clipData.Split(new[] { @",\""", @"\"",", @"\""" }, 
    StringSplitOptions.RemoveEmptyEntries);

答案 4 :(得分:0)

您可以尝试使用一点LINQ:

string excelData = "\\\" 1,234,123.00 \\\",\\\" 2,345.00 \\\", 342.00 ,\\\" 12,345.00 \\\"";

IEnumerable<string> cells = from x in excelData.Split(new string[] { "\\\"" }, StringSplitOptions.RemoveEmptyEntries)
                            let y = x.Trim(',').Trim()
                            where !string.IsNullOrWhiteSpace(y)
                            select y;

或者,如果您不喜欢这个建议,请尝试使用RegEx实现类似的模式。

相关问题