При сохранении в csv меняет формат ячейки excel

 

MRAK

Пользователь

Сообщений: 11
Регистрация: 13.05.2014

Создаю файл для печати маркировке на принтере, в столбик забиваю значения( 1-2,2-2 и т.д.), выбираю формат ячейки- текст. Сохраняю в формате .cvs, закрываю файл. открываю файл заново, в значения в ячейках уже стоят как дата ( 1-янв., 2-февр. и т.д.). Причем меняет не все значения а выборочно! Кто знает как с этим бороться?

 

Johny

Пользователь

Сообщений: 2737
Регистрация: 21.12.2012

Ожидаемое поведение, так как CSV файл — это просто текстовый файл.

There is no knowledge that is not power

 

Hugo

Пользователь

Сообщений: 23257
Регистрация: 22.12.2012

Откройте файл блокнотом и убедитесь, что там всё в порядке. Или нет…

 

MRAK

Пользователь

Сообщений: 11
Регистрация: 13.05.2014

Блокнотом открыл, все в порядке!

 

JayBhagavan

Пользователь

Сообщений: 11833
Регистрация: 17.01.2014

ПОЛ: МУЖСКОЙ | Win10x64, MSO2019x64

Попробуйте ставить вначале одинарную кавычку, например, так:
‘1-2

<#0>
Формула массива (ФМ) вводится Ctrl+Shift+Enter
Memento mori

 

Hugo

Пользователь

Сообщений: 23257
Регистрация: 22.12.2012

Да просто не нужно открывать его в Экселе :)
Или открывать через импорт внешних данных, по пути указывая нужный формат столбцам.

 

MRAK

Пользователь

Сообщений: 11
Регистрация: 13.05.2014

Я его потом открываю в другой программе, для принтера, и там появляется абракадабра!

 

MRAK, кодировка? Приложите какой-нибудь файл .csv, который нормально открывается в программе.

 

JayBhagavan

Пользователь

Сообщений: 11833
Регистрация: 17.01.2014

ПОЛ: МУЖСКОЙ | Win10x64, MSO2019x64

Абракадабра из-за неверной кодировки кириллицы? Какую кодировку понимает программа и в какой кодировке сохраняет эксель согласуйте. Я так понимаю.

<#0>
Формула массива (ФМ) вводится Ctrl+Shift+Enter
Memento mori

 

MRAK

Пользователь

Сообщений: 11
Регистрация: 13.05.2014

Абракадабра получается потому что в ячейке формат даты, программа для принтера не понимает кирилицу. Нужно както сделать что бы при сохранении не менялся формат ячейки.

 

MRAK

Пользователь

Сообщений: 11
Регистрация: 13.05.2014

Вот пример файла, 11-1 он меняет на дату!!!

 

Hugo

Пользователь

Сообщений: 23257
Регистрация: 22.12.2012

В этом файле нет 11-1 — ближайшее похожее 11-1C1
Вообще если программа принтера требует csv — то она должна сама корректно разбираться с этими значениями.
Ну а если Вы ей подсовываете такой файл как этот — то виноваты Вы. Блокнот ведь есть в хозяйстве? Откройте и исправьте.

 

MRAK

Пользователь

Сообщений: 11
Регистрация: 13.05.2014

Естественно нет 11-1, потому что Exel поменял формат ячейки на дату при сохранении, в этом вся и проблема! А программа понимает только файлы с расширением csv!

 

JayBhagavan

Пользователь

Сообщений: 11833
Регистрация: 17.01.2014

ПОЛ: МУЖСКОЙ | Win10x64, MSO2019x64

#14

14.05.2014 10:38:21

Цитата
MRAK пишет:
Вот пример файла

А покажите, пожалуйста, из чего этот цсв получен. Если Вы в экселе в ячейку вводите «11-1», а формат ячейки НЕ текстовый, то, да, эксель выправит это на дату. Выделите столбец, где будут цифры через дефис вводится, и присвойте ему текстовый формат.

<#0>
Формула массива (ФМ) вводится Ctrl+Shift+Enter
Memento mori

 

Hugo

Пользователь

Сообщений: 23257
Регистрация: 22.12.2012

Если Вы вводите в ячейку 11-1 и тут же видите что там 11.Jan — то глупо надеяться, что в csv будет 11-1…
И вообще — есть другие спецпрграммы для работы с csv — может быть они будут удобнее. Эксель не вполне годится для такой работы, у нас используют что-то другое.

P.S. А кто говорил «Блокнотом открыл, все в порядке!»?

Изменено: Hugo14.05.2014 10:49:40

 

MRAK

Пользователь

Сообщений: 11
Регистрация: 13.05.2014

#16

14.05.2014 11:42:55

Цитата
Hugo пишет:
Если Вы вводите в ячейку 11-1 и тут же видите что там 11.Jan — то глупо надеяться, что в csv будет 11-1…

Я вижу 11-1 и даже после сохранения вижу тоже, а вот при повторном открытии уже появляется 11.Jan

 

Hugo

Пользователь

Сообщений: 23257
Регистрация: 22.12.2012

Так то при повторном! Я же говорил — не открывайте Экселем, зачем Вам это?

 

MRAK

Пользователь

Сообщений: 11
Регистрация: 13.05.2014

#18

14.05.2014 12:26:04

Я открываю программой для принтера и там уже стоит дата!

Цитата
JayBhagavan пишет: Выделите столбец, где будут цифры через дефис вводится, и присвойте ему текстовый формат.

Я пробовал и так как вы говорите и до ввода данных в ячейку присваивал текстовый формат, все равно при сохранении он меняет формат на дату!

 

MRAK

Пользователь

Сообщений: 11
Регистрация: 13.05.2014

Только что попробовал открыть этот файл Опенофисом, все в порядке. сохранил, открыл в программе для принтера все ок! Буду пользоваться Опенофисом

 

Hugo

Пользователь

Сообщений: 23257
Регистрация: 22.12.2012

Тогда как вариант — попробуйте в файле csv взять эти 11-1 в кавычки, для начала исправьте в блокноте. Если принтер примет — тогда можно думать, как этого достичь Экселем.

P.S. Чуть поэксперементировал — думаю нужно читать мануал или мучить эту программу принтера. Ну или её разработчиков.

P.P.S. — можете показать файл после Опенофиса?

Изменено: Hugo14.05.2014 12:42:02

 

MRAK

Пользователь

Сообщений: 11
Регистрация: 13.05.2014

#21

14.05.2014 12:57:54

Цитата
Hugo пишет:
P.P.S. — можете показать файл после Опенофиса?

Вы можете открыть тот же файл что я выкладывал опенОфисом, там все ок!

 

Hugo

Пользователь

Сообщений: 23257
Регистрация: 22.12.2012

Как из такого (из блокнота):
11-C
11-C
11-C
11-янв
11-янв
11-янв
11-фев
11-фев
11-мар
11-мар
может быть ОК в опенофисе?

У меня нигде нет Опенофиса, т.ч. проверить сам не могу. Да и глупо проверять — ну не может быть такого  :)

Изменено: Hugo14.05.2014 13:03:13

 

MRAK

Пользователь

Сообщений: 11
Регистрация: 13.05.2014

Верить или нет это ваше личное дело, я проверил уже 4 файла. Exel открывает и показывает дату, ОпенОфис показывает то что надо!

 

Hugo

Пользователь

Сообщений: 23257
Регистрация: 22.12.2012

#24

14.05.2014 13:34:20

Речь о том, что там в этом csv. Что показывают Эксель и опенофис — это их дело. С Экселем всё понятно…
Вы сами сказали что в блокноте всё было ОК — значит в блокноте вероятно было 11-1, а не то, что тут на форуме — 11-янв.
Ладно, мне в общем всё равно, мне печатать не нужно. Работайте как считаете удобным…

@John2064  wrote:

1. Use Excel format function, 44928 can be converted to MM/DD/YYY Date format, but when save file into CSV, format becomes M/DD/YYYY.

2, using = Text( original cell , «MM/DD/YYYY») , when save file into CSV file, format becomes M/DD/YYYY failed (instead of MM)

Both assertions are incorrect.  I suspect you are opening the CSV file (directly?) with Excel.

Instead,  open the CSV with Notepad to see how the data is written to the file.

——

@John2064wrote:

3. Open Source file via Excel, Data/ From Text/CSV, File opened with correct Date format , when save to CSV file, format becomes M/DD/YYYY failed again.

That is correct, but only because you chose a Date format.  In that case, Excel interpets the file data just as if we had typed them into a cell formatted as General.

Instead, choose the Text format for the column in order to preserve the appearance in the CSV file.

However, beware that that might have undesirable consequences.

So, if you want the data to remain as numeric, the only work-around is to re-assert the desired format after importing the file.

«It is what it is».

МИР ВАШЕМУ ДОМУ!!!

57 / 58 / 7

Регистрация: 01.04.2009

Сообщений: 890

Записей в блоге: 1

1

21.03.2013, 14:17. Показов 24578. Ответов 14


Студворк — интернет-сервис помощи студентам

Здравствуйте друзья.
В файле имеются числа (номер счетчика и его показания):
007778997 784
0032432 78975

При сохранении этих данных в формат шаблона («CSV (разделители — запятые)») в конечном файле вышеприведенные значения отображаются так:
7778997 784
32432 78975

т.е. без нулей.
Менял формат ячейки, ставил числовой и убирал знаки после запятой.
Проблема остается.
Как быть?



0



5942 / 3154 / 698

Регистрация: 23.11.2010

Сообщений: 10,524

21.03.2013, 14:41

2

Формат ячеек — текстовый. Сохранить в csv.
Открывать: получить внешние данные — Из текста — вот здесь надо отметить, что ячейки будут Текстовые, тогда 0 будет отображаться



1



МИР ВАШЕМУ ДОМУ!!!

57 / 58 / 7

Регистрация: 01.04.2009

Сообщений: 890

Записей в блоге: 1

21.03.2013, 14:50

 [ТС]

3

Ставлю текстовый формат, некоторые номера показывает так: «4,79803E+13».

Цитата
Сообщение от Fairuza
Посмотреть сообщение

Открывать: получить внешние данные — Из текста — вот здесь надо отметить, что ячейки будут Текстовые, тогда 0 будет отображаться

Это в экзеле открывать таким образом?



0



5942 / 3154 / 698

Регистрация: 23.11.2010

Сообщений: 10,524

21.03.2013, 14:53

4

Текстовый надо ставить в исходном файле. Пришлите кусочек Вашего файла.

Добавлено через 1 минуту

Цитата
Сообщение от A_R_S
Посмотреть сообщение

Это в экзеле открывать таким образом?

Да.



1



МИР ВАШЕМУ ДОМУ!!!

57 / 58 / 7

Регистрация: 01.04.2009

Сообщений: 890

Записей в блоге: 1

21.03.2013, 14:56

 [ТС]

5

Вот файл.

Вложения

Тип файла: xls 1.xls (41.0 Кб, 61 просмотров)



0



МИР ВАШЕМУ ДОМУ!!!

57 / 58 / 7

Регистрация: 01.04.2009

Сообщений: 890

Записей в блоге: 1

21.03.2013, 15:42

 [ТС]

6

Цитата
Сообщение от Fairuza
Посмотреть сообщение

Да.

Вы не подскажите где именно это делается?

Добавлено через 24 минуты
Получилось, открываю в текстовом файле csv отображает нормально (с нулями). Открываю экзелем там на подобии
«4,79803E+13». Думаю при заливке «4,79803E+13» не повлияет, ведь при открытии блокнотом отображается все верно?



0



5942 / 3154 / 698

Регистрация: 23.11.2010

Сообщений: 10,524

21.03.2013, 15:51

7

У меня все получилось.
Давайте по порядку: сохраняете свой файл в csv. открываете новую книгу или новый лист в любой книге — Данные — Получить внешние данные — Из текста — Находите сохраненный в csv файл — импорт. Здесь отмечаете — С разделителями (обратите внимание на кодировку, если что поставьте правильную) — Далее. Символ-разделитель отмечаете — Далее. Вот тут будет Формат столбца данных — Каждый (!) столбец надо отметить поочередно, в столбце где с нулями, отметьте Текстовый, и -далее разберетесь — Готово.



1



МИР ВАШЕМУ ДОМУ!!!

57 / 58 / 7

Регистрация: 01.04.2009

Сообщений: 890

Записей в блоге: 1

21.03.2013, 15:54

 [ТС]

8

Получилось, открываю в текстовом файле csv отображает нормально (с нулями). Открываю экзелем там на подобии
«4,79803E+13». Думаю при заливке «4,79803E+13» не повлияет, ведь при открытии блокнотом отображается все верно?



0



5942 / 3154 / 698

Регистрация: 23.11.2010

Сообщений: 10,524

21.03.2013, 15:55

9

посмотрите

Миниатюры

Как правильно сохранить числа в csv файл?
 



1



0 / 0 / 0

Регистрация: 20.07.2020

Сообщений: 9

20.07.2020, 18:44

10

Здравствуйте. Я — новичок (во всех смыслах). Мне нужно в создать файл .csv, в котором в одной из колонок должно быть число из 14 цифр. Создаю, сохраняю csv (разделитель запятые). При этом программа предупреждает «если сохранить в csv, некоторые возможности станут недоступными» — отвечаю «ДА». Сразу же закрываю этот файл «крестиком» — опять выходит вопрос: «Вы хотите сохранить изменения в файле?» (хотя ничего не изменял) — снова отвечаю «ДА». Тут же открываю созданный только что файл — вместо нужных цифр стоят 14, но других….. Как исправить? подскажите, пожалуйста, попроще..



0



5942 / 3154 / 698

Регистрация: 23.11.2010

Сообщений: 10,524

21.07.2020, 07:06

11

Цитата
Сообщение от Avusa
Посмотреть сообщение

вместо нужных цифр стоят 14, но других.

интересно каких…



0



0 / 0 / 0

Регистрация: 20.07.2020

Сообщений: 9

21.07.2020, 09:12

12

Не тех, которые я ввожу до сохранения файла.



0



0 / 0 / 0

Регистрация: 20.07.2020

Сообщений: 9

21.07.2020, 09:20

13

Fairuza, иллюстрирую свою проблему картинкой. Может, всё-таки, сообразите, как мне помочь…

Миниатюры

Как правильно сохранить числа в csv файл?
 



0



малоболт

1143 / 442 / 193

Регистрация: 30.01.2020

Сообщений: 1,095

21.07.2020, 11:46

14

Цитата
Сообщение от Avusa
Посмотреть сообщение

иллюстрирую свою проблему картинкой.

Перед сохранением в CSV поменяйте формат отображения либо на числовой, с 0 знаков после запятой, либо на текстовый. В csv экспортируется то, что отображается: 3,85E13, соответственно при импорте этого csv в эксель получите 385 и 11 нулей.

И сохраняйте один раз в csv. Когда предложит сохранить ещё при закрытии файла — лучше не сохранять.



1



0 / 0 / 0

Регистрация: 20.07.2020

Сообщений: 9

21.07.2020, 18:02

15

Punkt5, Большое спасибо за толковый ответ! У меня получилось. Надеюсь, и те люди, для которых этот файл предназначался, получат его в том же виде, как и у меня.

Однако при сохранении и закрытии файла этот .csv раз 15 спрашивал «сохранять/не сохранять». Поэтому ваш совет «лучше не сохранять» не прокатил…



0



   Aleksey1989

25.11.13 — 12:12

Добрый день. Возникла неожиданная проблема при сохранении документа xls (формат Excel’я) в csv — цифровые значения ячеек, имеющие 20 разрядов, сохраняются в сокращенном виде:  н-р 5,08178Е + 19. Как сделать так, чтобы сохранялись числа в изначальном виде?

   ДенисЧ

1 — 25.11.13 — 12:14

формат ячейки укажи текстовым

   Aleksey1989

2 — 25.11.13 — 12:16

(1) Не помогает — число обрезается. Т.е. в экселе было число 50817832390390239320, а в результате указания формата получается число 50817832390390000000.

   Aleksey1989

3 — 25.11.13 — 12:16

+(2) Количество нулей в конце результирующего числа примерное.

   User_Agronom

4 — 25.11.13 — 12:17

Покажи команду как сохраняешь.

Ну и как формируешь всю бодягу

   User_Agronom

5 — 25.11.13 — 12:17

   Aleksey1989

6 — 25.11.13 — 12:30

(5) Эта тема про другое. Вы сами попробуйте создать экселевский файл, вбить в какую-нибудь ячейку число 20ти значной разрядности и после этого сохранить в csv файл — пройзойдет ошибка, о которой я написал в 0-м посте.

   User_Agronom

7 — 25.11.13 — 12:33

(6) Если вы в макете укажете текст, то это будет текст.

Т.е. набор символов

   User_Agronom

8 — 25.11.13 — 12:34

Или это в Excel-е танец проходит?

Тогда пардон. Я думал из 1с-ки..

   Стрелок

9 — 25.11.13 — 12:34

из 1С или из екселя?

   Aleksey1989

10 — 25.11.13 — 12:37

(8) танец происходит в Excel-е, при этом мне, как танцору, явно кое-что мешает :)))

   Стрелок

11 — 25.11.13 — 12:39

какой формат ячейки у файла xls?

какой формат числа у файла xls?

   Lama12

12 — 25.11.13 — 12:44

(0)Не храни в ексель в ячейке с типом число, числа больше 15 знаков.

   Lama12

13 — 25.11.13 — 12:51

Excel не СУБД, у него свои скромные ограничения на число. :)

   Aleksey1989

14 — 25.11.13 — 12:59

(11) формат ячейки — текстовый. Но при сохранении в csv он превращается в Общий.

что за формат числа?

   babytype

15 — 25.11.13 — 13:10

(14) а если csv через блокнот открыть?

   Aleksey1989

16 — 25.11.13 — 13:15

(15) То же самое — проблема в том, что Excel при сохранении в csv сам преобразует текстовую строку, содержащую число, в число, при этом, посколько сам эксель может работать только максимум с 15-тью разрядами, остальную часть числа обнуляет.

Вообщем буду писать обработку, которая из 1С-ки будет выгружать необходимые мне данные в csv.

   babytype

17 — 25.11.13 — 13:22

(16) Эксель 2010. Только что вбил руками в ячейку с форматом «Строка» 25 цифер, сохранил в csv, открыл блокнотом — все цифры на месте.

  

babytype

18 — 25.11.13 — 13:24

+(16) Если же после этого еще раз открыть csv Экселем и пересохранить — то да, обрезает, потому что в сsv не хранятся форматы ячеек.

Время на прочтение
11 мин

Количество просмотров 366K

CSV является стандартом де-факто для связи между собой разнородных систем, для передачи и обработки объемных данных с «жесткой», табличной структурой. Во многих скриптовых языках программирования есть встроенные средства разбора и генерации, он хорошо понятен как программистам, так и рядовым пользователям, а проблемы с самими данными в нем хорошо обнаруживаются, как говорится, на глаз.

История этого формата насчитывает не менее 30 лет. Но даже сейчас, в эпоху повального использования XML, для выгрузки и загрузки больших объемов данных по-прежнему используют CSV. И, несмотря на то, что сам формат довольно неплохо описан в RFC, каждый его понимает по-своему.

В этой статье я попробую обобщить существующие знания об этом формате, указать на типичные ошибки, а также проиллюстрировать описанные проблемы на примере кривой реализации импорта-экспорта в Microsoft Office 2007. Также покажу, как обходить эти проблемы (в т.ч. автоматическое преобразование типов Excel-ом в DATETIME и NUMBER) при открытии .csv.

Начнем с того, что форматом CSV на самом деле называют три разных текстовых формата, отличающихся символами-разделителями: собственно сам CSV (comma-separated values — значения, разделенные запятыми), TSV (tab-separated values — значения, разделенные табуляциями) и SCSV (semicolon separated values — значения, разделенные точкой с запятой). В жизни все три могут называться одним CSV, символ-разделитель в лучшем случае выбирается при экспорте или импорте, а чаще его просто «зашивают» внутрь кода. Это создает массу проблем в попытке разобраться.

Как иллюстрацию возьмем казалось бы тривиальную задачу: импортировать в Microsoft Outlook данные из таблицы в Microsoft Excel.

В Microsoft Excel есть средства экспорта в CSV, а в Microsoft Outlook — соответствующие средства импорта. Что могло быть проще — сделал файлик, «скормил» почтовой программе и — дело сделано? Как бы не так.

Создадим в Excel тестовую табличку:

Текстовая табличка

… и попробуем экспортировать ее в три текстовых формата:

«Текст Unicode» Кодировка — UTF-16, разделители — табуляция, переводы строк — 0×0D, 0×0A, объем файла — 222 байт
«CSV (разделители — запятые)» Кодировка — Windows-1251, разделители — точка с запятой (не запятая!), во второй строке значение телефонов не взято в кавычки, несмотря на запятую, зато взято в кавычки значение «01;02», что правильно. Переводы строк — 0×0D, 0×0A. Объем файла — 110 байт
«Текстовые файлы (с разделителями табуляции)» Кодировка — Windows-1251, разделители — табуляция, переводы строк — 0×0D, 0×0A. Значение «01;02» помещено в кавычки (без особой нужды). Объем файла — 110 байт

Какой вывод мы делаем из этого?.. То, что здесь Microsoft называет «CSV (разделители — запятые)», на самом деле является форматом с разделителями «точка с запятой». Формат у Microsoft — строго Windows-1251. Поэтому, если у вас в Excel есть Unicode-символы, они на выходе в CSV отобразятся в вопросительные знаки. Также то, что переводами строк является всегда пара символов, то, что Microsoft тупо берет в кавычки все, где видит точку с запятой. Также то, что если у вас нет Unicode-символов вообще, то можно сэкономить на объеме файла. Также то, что Unicode поддерживается только UTF-16, а не UTF-8, что было бы сильно логичнее.

Теперь посмотрим, как на это смотрит Outlook. Попробуем импортировать эти файлы из него, указав такие же источники данных. Outlook 2007: Файл -> Импорт и экспорт… -> Импорт из другой программы или файла. Далее выбираем формат данных: «Значения, разделенные запятыми (Windows)» и «Значения, разделенные табуляцией (Windows)».

«Значения, разделенные табуляцией(Windows)» Скармливаем аутлуку файл tsv, с разделенными табуляцией значениями и!.. — чтобы вы думали?.. Outlook склеивает поля и табуляцию не замечает. Заменяем в файле табуляцию на запятые и, как видим, поля уже разбирает, молодец.
«Значения, разделенные запятыми (Windows)» А вот аутлук как раз понимает все верно. Comma — это запятая. Поэтому ожидает в качестве разделителя запятую. А у нас после экселя — точка с запятой. В итоге аутлук распознает все неверно.

Два майкрософтовских продукта не понимают друг друга, у них напрочь отсутствует возможность передать через текстовый файл структурированные данные. Для того, чтобы все заработало, требуются «пляски с бубном» программиста.

Мы помним, что Microsoft Excel умеет работать с текстовыми файлами, импортировать данные из CSV, но в версии 2007 он делает это очень странно. Например, если просто открыть файл через меню, то он откроется без какого-либо распознавания формата, просто как текстовый файл, целиком помещенный в первую колонку. В случае, если сделать дабл-клик на CSV, Excel получает другую команду и импортирует CSV как надо, не задавая лишних вопросов. Третий вариант — вставка файла на текущий лист. В этом интерфейсе можно настраивать разделители, сразу же смотреть, что получилось. Но одно но: работает это плохо. Например, Excel при этом не понимает закавыченных переводов строк внутри полей.

Более того, одна и та же функция сохранения в CSV, вызванная через интерфейс и через макрос, работает по-разному. Вариант с макросом не смотрит в региональные настройки вообще.

Стандарта CSV как такового, к сожалению, нет, но, между тем, существует т.н. memo. Это RFC 4180

2005-го

года, в котором описано все довольно толково. За неимением ничего большего, правильно придерживаться хотя бы RFC. Но для совместимости с Excel следует учесть его собенности.

Вот краткая выжимка рекомендаций RFC 4180 и мои комментарии в квадратных скобках:

  • между строками — перевод строки CRLF [на мой взгляд, им не стоило ограничивать двумя байтами, т.е. как CRLF (0×0D, 0×0A), так и CR 0×0D]
  • разделители — запятые, в конце строки не должно быть запятой,
  • в последней строке CRLF не обязателен,
  • первая строка может быть строкой заголовка (никак не помечается при этом)
  • пробелы, окружающие запятую-разделитель, игнорируются.
  • если значение содержит в себе CRLF, CR, LF (символы-разделители строк), двойную кавычку или запятую (символ-разделитель полей), то заключение значения в кавычки обязательно. В противном случае — допустимо.
  • т.е. допустимы переводы строк внутри поля. Но такие значения полей должны быть обязательно закавычены,
  • если внутри закавыченной части встречаются двойные кавычки, то используется специфический квотинг кавычек в CSV — их дублирование.

Вот в нотации ABNF описание формата:

 file = [header CRLF] record *(CRLF record) [CRLF]
   header = name *(COMMA name)
   record = field *(COMMA field)
   name = field
   field = (escaped / non-escaped)
   escaped = DQUOTE *(TEXTDATA / COMMA / CR / LF / 2DQUOTE) DQUOTE
   non-escaped = *TEXTDATA
   COMMA = %x2C
   DQUOTE =  %x22
   LF = %x0A
   CRLF = CR LF
   TEXTDATA =  %x20-21 / %x23-2B / %x2D-7E
 

Также при реализации формата нужно помнить, что поскольку здесь нет указателей на число и тип колонок, поскольку нет требования обязательно размещать заголовок, здесь есть условности, о которых необходимо не забывать:

  • строковое значение из цифр, не заключенное в кавычки может быть воспринято программой как числовое, из-за чего может быть потеряна информация, например, лидирующие нули,
  • количество значений в каждой строке может отличаться и необходимо правильно обрабатывать эту ситуацию. В одних ситуациях нужно предупредить пользователя, в других — создавать дополнительные колонки и заполнять их пустыми значениями. Можно определиться, что количество колонок задается заголовком, а можно добавлять их динамически, по мере импорта CSV,
  • Квотить кавычки через «слэш» не по стандарту, делать так не надо.
  • Поскольку типизации полей нет, нет и требования к ним. Разделители целой и дробной частей в разных странах разные, и это приводит к тому, что один и тот же CSV, сгенрированный приложением, в одном экселе «понимается», в другом — нет. Потому что Microsoft Office ориентируется на региональные настройки Windows, а там может быть что угодно. В России там указано, что разделитель — запятая,
  • Если CSV открывать не через меню «Данные», а напрямую, то Excel лишних вопросов не задает, и делает как ему кажется правильным. Например, поле со значением 1.24 он понимает по умолчанию как «24 января»
  • Эксель убивает ведующие нули и приводит типы даже тогда, когда значение указано в кавычках. Делать так не надо, это ошибка. Но чтобы обойти эту проблему экселя, можно сделать небольшой «хак» — значение начать со знака «равно», после чего поставить в кавычках то, что необходимо передать без изменения формата.
  • У экселя есть спецсимвол «равно», который в CSV рассматривается как идентификатор формулы. То есть, если в CSV встретится =2+3, он сложит два и три и результат впишет в ячейку. По стандарту он это делать не должен.

Пример валидного CSV, который можно использовать для тестов:

Фамилия, Имя, Адрес, Город/штат, индекс, просто строка
Иванов,Иван, Ленина 20, Москва, 08075, "1/3"
Tyler, John,110 terrace, PA,20121, "1.24"
"Петров 
""Кул""", Петя,120 Hambling St., NJ,08075, "1,24"
Смирнов,Вася,"7452 Street ""Near the Square"" road", York, 91234, "3-01"
,Миша,,Ленинград, 00123, "03-01"
"Джон ""Черная голова"", Клод",Рок,"", Маями бич,00111, "0000"
Сергей,,

точно такой же SCSV:

Фамилия; Имя; Адрес;  Город/штат; индекс; просто строка
Иванов;Иван; Ленина 20; Москва; 08075;"1/3"
Tyler; John;110 terrace; PA; 20121;"1.24"
"Петров 
""Кул"""; Петя;120 Hambling St.; NJ;08075;"1,24"
Смирнов;Вася;"7452 Street ""Near the Square"" road"; York; 91234;"3-01"
;Миша;;Ленинград; 00123;"03-01"
"Джон ""Черная голова""; Клод";Рок;""; Маями бич;00111; "0000"
Сергей;;

Первый файлик, который реально COMMA-SEPARATED, будучи сохраненным в .csv, Excel-ом не воспринимается вообще.

Второй файлик, который по логике SCSV, экселом воспринимается и выходит вот что:

Ошибки Excel-я при импорте:

  1. Учлись пробелы, окружающие разделители
  2. Последний столбец вообще толком не распознался, несмотря на то, что данные в кавычках. Исключение составляет строка с «Петровым» — там корректно распозналось 1,24.
  3. В поле индекс Excel «опустил» ведущие нули.
  4. в самом правом поле последней строки пробелы перед кавычками перестали указывать на спецсимвол

Если же воспользоваться функционалом импорта (Данные -> Из файла) и обозвать при импорте все поля текстовыми, то будет следующая картина:

С приведением типов сработало, но зато теперь не обрабатываются нормально переводы строк и осталась проблема с ведущими нулями, кавычками и лишними пробелами. Да и пользователям так открывать CSV крайне неудобно.

Есть эффективный способ, как заставить Excel не приводить типы, когда это нам не нужно. Но это будет CSV «специально для Excel». Делается это помещением знака «=» перед кавычками везде, где потенциально может возникнуть проблема с типами. Заодно убираем лишние пробелы.

Фамилия;Имя;Адрес;Город/штат;индекс;просто строка
Иванов;Иван;Ленина 20;Москва;="08075";="1/3"
Tyler; John;110 terrace;PA;="20121";="1.24"
"Петров 
""Кул""";Петя;120 Hambling St.;NJ;="08075";="1,24"
Смирнов;Вася;"7452 Street ""Near the Square"" road";York;="91234";="3-01"
;Миша;;Ленинград;="00123";="03-01"
"Джон ""Черная голова"";Клод";Рок;"";Маями бич;="00111";="0000"
Сергей;;

И вот что случаеся, если мы открываем этот файлик в экселе:

Резюмирую.

Чтобы сгенерировать такой CSV, которым можно было бы пользоваться, пользователю нужно дать возможность сделать следующие настройки перед экспортом:

  1. выбрать кодировку. Как правило, важно UTF-8, UTF-16, Windows-1251, KOI8-R. Чаще всего, других вариантов нет. Одна из них должна идти по умолчанию. В случае, если данные содержат символы, не имеющие аналогов в целевой кодировке, нужно предупреждать пользователя, что данные будут битые;
  2. выбрать разделитель между полями. Варианты — табуляция, запятая, точка с запятой. По умолчанию — точка с запятой. Не забыть, что если разделитель вводится в тексте, то будет очень непросто ввести туда табуляцию, это еще и непечатный символ;
  3. выбрать разделитель между строками (CRLF 0×0D 0×0A или CR 0×0D);
  4. выбрать разделитель целой и дробной части для числовых данных (точка или запятая).
  5. выбрать, выводить ли строку заголовка;
  6. выбрать, каким образом осуществлять квотинг спецсимволов (особенно переводов строк и кавычек). В принципе, можно отступиться от стандарта и квотировать их как n и «, но нужно в этом случае не забыть квотировать сами n, если они встретятся и не забыть сделать это опцией при экспорте-импорте. Но совместимость пойдет лесом, потому что любой RFC-стандартный парсер конструкцию …,»abc«»,… посчитает за ошибку;
  7. совсем в идеале — поставить галочку «для Excel» и учитывать там те нестандартности, которые внесла Майкрософт. К примеру, заменять значения числовых полей, «похожих на дату», на конструкцию =»<значение поля>«.
  8. определиться, нужно ли оставлять «хвост» из пустых разделителей, если он образуется. Например, из 20 полей только первое содержит данные, а остальные пустые. В итоге, в строке можно либо ставить после первого 19 разделителей, либо не ставить. Для больших объемов данных это может спасти миллисекунды обработки и уменьшить размер файла.

Чтобы построить хороший и удобный импортер CSV, необходимо помнить о следующем:

  1. разбор файла нужно делать по лексемам в соответствии с грамматикой выше или пользоваться хорошо зарекомендовавшими себя готовыми библиотеками (Excel работает иначе, потому с импортом проблема);
  2. предоставлять пользователю возможность выбрать кодировку (топ 4 достаточно);
  3. предоставлять пользователю возможность выбрать разделитель между полями (запятая, табуляция, точка с запятой достаточно);
  4. предоставлять пользователю возможность выбрать разделитель между строками, но кроме вариантов CR и CRLF нужно предусмотреть «CR или CRLF». Это связано с тем, что, например, Excel при экспорте таблицы с переводами строк внутри ячеек экспортирует эти переводы строк как CR, а остальные строки разделяет CRLF. При этом при импорте файла ему все равно, CR там или CRLF;
  5. предоставлять пользователю возможность выбрать разделитель между целой и дробной частей (запятая или точка);
  6. определиться с методом разбора — сначала читаем все в память, потом обрабатываем или обрабатываем строку за строкой. В первом случае может понадобиться больше памяти, во втором случае — ошибка в середине вызовет только частичный импорт, что может вызвать проблемы. Предпочительнее первый вариант.

Рауф Алиев,
заместитель технического директора Mail.Ru Group

Понравилась статья? Поделить с друзьями:
  • При удалении дубликатов какие строки удаляются excel выше или ниже
  • При сохранении excel создается tmp
  • При удалении диаграммы excel
  • При сохранении excel появляется файл
  • При удаление формулы в excel