Разделить с использованием разделителя, за исключением случаев, когда разделитель экранирован

Я читаю данные буфера обмена, поступающие из Excel

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

но, к сожалению, excel передает текст ячейки вместо значений ячейки. Когда ячейки используют специальное форматирование (например, тысячный seperator), данные буфера обмена для ряда ячеек в столбцах, которые выглядят следующим образом:

  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) здесь: Разделить строку, основанную на каждом случае, когда детерминированные конечные автоматы достигают конечного состояния?

Во-первых, я имел дело с данными из 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; то это будет превращено в a ", который может быть или не быть желательным.

Есть много способов сделать это. Один из неэлегантных способов работы:

  1. Преобразуйте \ ", \" в табуляцию или какой-либо другой разделитель (предположим, что вы оставили некоторые из них) в вашем примере, потому что иначе строка не согласована
  2. Сбросьте все остальные запятые
  3. Разделите все оставшиеся \ "
  4. Преобразуйте разделитель (например, вкладку) обратно в запятую

Теперь у вас есть то, что вы хотели на первом месте

Я согласен с Кайлом в отношении вашей строки, возможно, не последовательной.

Вместо первого шага Кайла вы можете использовать

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

Из вашего примера ввода мы видим, что есть три «нежелательные» последовательности символов:

 \" \", ,\" 

Итак, добавьте все эти последовательности во входной массив для метода Split :

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

Это даст вам массив, содержащий несколько пустых элементов. Если это проблема, используйте StringSplitOptions.RemoveEmptyEntries вместо StringSplitOptions.None :

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

Вы можете попытаться использовать немного 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.

  • Если строка найдена в диапазоне 'Yes' else 'No'
  • Извлечь почтовый индекс после аббревиатуры государства
  • Сравнение содержимого ячейки со строкой в ​​Excel
  • EXCEL VBA: соответствует части строки
  • Очистить содержимое любой ячейки в столбце, содержащей двойную кавычку в текстовой строке
  • VBA удаляет соответствующие имена и фамилии в двух листах
  • Невозможно назначить String из переменной в качестве имени листа
  • Получение данных из источника HTML в VBA (excel)
  • Код Vba для группировки чисел, которые являются 31-м символом в строке с разрывом строки между последовательными номерами
  • excel vba - удалить определенный текст в статье
  • vba excel - найти шаблон строки
  • Давайте будем гением компьютера.