powered by simpleCommunicator - 2.0.36     © 2025 Programmizd 02
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / Python - символы _x000D_ при экспорте в xlsx
19 сообщений из 19, страница 1 из 1
Python - символы _x000D_ при экспорте в xlsx
    #40066635
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Привет.
Сам я дельфист, пытаюсь бороться с одной фигней которая рождается где-то внутри питона которым занимается другой чел.
Этот чел упирается в то что у него ошибок не может быть, исправляйте сами где хотите, на стороне получателя этого файла.

Ситуация такая.
Данные лежат в базе Firebird-2.5
Кодировка всей базы win1251.
Приложение написанное на Delphi работает с базой без проблем.
В базе есть блоб-поля содержащие описание товара, многострочный текст.

Код: plsql
1.
2.
3.
4.
5.
CREATE TABLE STOV (
  ...
    DESCR         BLOB SUB_TYPE 1 SEGMENT SIZE 80 default '',
 ...
)



Из этой базы скрипт на питоне вытягивает данные и сохраняет в файл xlsx.
Проблема в том что в этом файле в ячейках с многострочным текстом появляется лишний символ переноса строки.
Прикол в том что в самом Excel он не отображается, но при загрузке из этого файла в 1С он становится видимым и далее везде фигурирует как непонятный хвост текста.

Внутри xlsx, файл sharedStrings.xml в котором хранятся строки, после форматирования, выглядит так

Код: html
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="6" uniqueCount="6">
    <si>
        <t>id</t>
    </si>
    <si>
        <t>full_name</t>
    </si>
    <si>
        <t>opisanie</t>
    </si>
    <si>
        <t>12-6187</t>
    </si>
    <si>
        <t>Маркер перманентный 1-4.6мм 8576/01 красный Centropen</t>
    </si>
    <si>
        <t>Маркер Permanent с клиновидным пишущим узлом с шириной линии 1-4,6 мм. _x000D_
Для письма на бумаге, резине, коже, пластмассе, металле. _x000D_
Перманентные чернила водостойкие и термостойкие на спиртовой основе.</t>
    </si>
</sst>



Видно что перевод строки тут есть, но так же, в конце каждой строки в многострочном поле торчат символы "_x000D_"

На сколько я понял, в XML шаблон вида _x****_ используется для кодирования юникодных символов их кодом.
Соответственно, _x000D_ это символ CR, но в Windows одиночный CR не является ни печатным ни управляющим символом,
поэтому он и не отображается т.к. не печатный, ни приводит к переводу строки т.к. не является управляющим.

В файле, после _x000D_ идет обычный перевод строки CR+LF (0D+0A) он и переводит строку.

Excel такие вещи обходит, символов _x000D_ в ячейке не видно, а вот 1С при чтении этого файла отображает _x000D_ как часть строки. При этом перенос строки есть.

Питонист говорит что делает свое черное дело таким кодом, и ошибок там никаких быть не может.

Код: python
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
       import pandas as pd
      from sqlalchemy.orm import sessionmaker #Run pip install sqlalchemy
      from sqlalchemy import create_engine

   q = """
           select 
           ...
           from table
           where 1=1
           and bost.nsklad = {nsklad}
           and bost.ost > 0
           and bost.id <> 855154
   """.format(base= base, nsklad = nsklad)

   engine = create_engine('firebird+fdb://USER:pass@10.0.0.6:3060/games?charset=win1251', echo=False)

   Session = sessionmaker(bind=engine)
   session = Session()

   df = pd.read_sql(q, session.bind)

            writer = pd.ExcelWriter(full_name, engine='xlsxwriter')
       df.to_excel(writer, startrow=1, index=False, sheet_name='Прайс')
       workbook = writer.book
       worksheet = writer.sheets['Прайс']
       #Ширина колонок
       worksheet.set_column(6, 6, 50)
       worksheet.set_column(7, 7, 25)
       worksheet.set_column(8, 8, 25)
       worksheet.set_column(11, 11, 50)
       writer.save()



Отступы в коде - какие мне дали, при передаче через чат.

Вопрос - откуда берется этот символ, нет ли каких-то известных граблей в питоне на эту тему? Гугление мне не помогло. Но я питон не знаю от слова "совсем".
...
Рейтинг: 0 / 0
Python - символы _x000D_ при экспорте в xlsx
    #40066898
vkle
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fraks
Данные лежат в базе Firebird-2.5
fraks
Вопрос - откуда берется этот символ
На показанном этапе, возможно, из базы и берется.
Если вопрос исследовательский, то, видимо, есть смысл посмотреть содержимое полей, а далее по ситуации.
Если же вопрос чисто практический, нужно избавиться от символа (или байта)... ну так и вырезать его перед использованием данных.
...
Рейтинг: 0 / 0
Python - символы _x000D_ при экспорте в xlsx
    #40066915
DHDD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
fraks,

берётся из xls/xlsx файла - это перевод строки.
заменяй вручную на то, что нужно.
...
Рейтинг: 0 / 0
Python - символы _x000D_ при экспорте в xlsx
    #40066944
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vkle
fraks
Данные лежат в базе Firebird-2.5
fraks
Вопрос - откуда берется этот символ
На показанном этапе, возможно, из базы и берется.
Если вопрос исследовательский, то, видимо, есть смысл посмотреть содержимое полей, а далее по ситуации.
Если же вопрос чисто практический, нужно избавиться от символа (или байта)... ну так и вырезать его перед использованием данных.


В базе кодировка win1251, НЕ юникод, там обычный cr+lf.
В файле xlsx перед тем самым cr+lf добавляется еще _x000D_ который портит всю малину.
Я бы понял если бы он вставлялся ВМЕСТО cr+lf, но оно именно добавляется.

Бороться с последствиями - достаточно неблагодарное занятие, тем более что это не полностью нам подконтрольно, и программисты 1С которые занимаются загрузкой данных из этого файла xlsx так и говорят - что вы в файл подсунули то мы и грузим.

Сейчас у меня выбор - показать нашему питонисту, в кавычках, в каком месте он облажался, или переписать этот скрипт на Delphi.
Я бы давно переписал, но у меня нет наработанного кода по работе с xlsx, есть только с xls. Конечно, это все можно решить, но это время. Если же есть реальная ошибка в питоньем коде - то достаточно эту ошибку убрать и на этом всё.

Может быть имеет значение что питоний код выполняется на linux, проблема в том как преобразовывается перенос строки windows-unix.
Может косяк в sqlalchemy или pandas, может быть нужно указать какие-то параметры по работе с переносом строк что бы получалось нужное, может быть проблема с драйвером firebird для питона.

Вопрос у меня в том - баг это или фича.
Если баг - исправляем, если фича - решаем как с этой фичей жить.
...
Рейтинг: 0 / 0
Python - символы _x000D_ при экспорте в xlsx
    #40066946
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DHDD
fraks,

берётся из xls/xlsx файла - это перевод строки.
заменяй вручную на то, что нужно.


То что берется из файла - я так и написал.
В исходных данных имеется обычный виндовый cr+lf
Вопрос - зачем там вместо cr+lf оказывается _x000D_+cr+lf
Причем если cr+lf это 2 символа, то _x000D_ это 7 символов.

Еще раз - мне нужно не удалить этот _x000D_ из файла, а сделать так что бы он туда не попадал.
...
Рейтинг: 0 / 0
Python - символы _x000D_ при экспорте в xlsx
    #40067002
x1ca4064
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fraks


Еще раз - мне нужно не удалить этот _x000D_ из файла, а сделать так что бы он туда не попадал.


Для этого нужно, чтобы входной текст не содержал символа 0D - как показало беглое гугление, эксел для разделения строк в ячейке использует только символ 0A, но при этом маскирует обработку _x000D_ :)
IMHO, удаление лучше делать в коде экспорта на питоне, чем в БД
...
Рейтинг: 0 / 0
Python - символы _x000D_ при экспорте в xlsx
    #40067048
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
x1ca4064
fraks


Еще раз - мне нужно не удалить этот _x000D_ из файла, а сделать так что бы он туда не попадал.


Для этого нужно, чтобы входной текст не содержал символа 0D - как показало беглое гугление, эксел для разделения строк в ячейке использует только символ 0A, но при этом маскирует обработку _x000D_ :)
IMHO, удаление лучше делать в коде экспорта на питоне, чем в БД


В БД, которая работает в кодировке win1251, совершенно легитимно находится обычный виндовый перевод строки, состоящий из двух символов CR+LF они же 0D 0A. Никто ни за каким надом не будет ломать работу основной программы, у которой все в порядке.

Excel может быть и маскирует, но в файле имеется строка символов _x000D_ которые появились там еще до того как Excel коснулся этого файла. Как-то он разбирается с этой комбинацией. Но иной софт, в частности 1С, символы cr+lf понимают правильно, а символы _x000D_ воспринимают как текст.

Если из файла символы _x000D_ удалить, оставив только обычный cr+lf, т.е. 0D 0A - то в Excel ничего не меняется, переводы строк остаются на месте.

Еще раз - Excel как-то с ними разбирается, Excel молодец, но мне нужно что бы эти левые символы не писались в файл в питоне, т.к. далее с этим файлом работает совсем не Excel.

Ладно бы, если какой-то питоний модуль в используемой цепочке вообще бы не умел работать с переводами строк, но он переводы строк видит и сует к ним лишнее. С какой целью он это делает и в каком месте?
...
Рейтинг: 0 / 0
Python - символы _x000D_ при экспорте в xlsx
    #40067049
x1ca4064
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fraks

Ладно бы, если какой-то питоний модуль в используемой цепочке вообще бы не умел работать с переводами строк, но он переводы строк видит и сует к ним лишнее. С какой целью он это делает и в каком месте?


Вероятно, формат требует, чтобы перевод строки был 0A, в целях "совместимости" эксел допускает наличие символа 0D и _x000D_, другие программы это могут не уметь.
Если в ячейку эксела запихать символ 0D, эффект, скорее всего, будет таким же (не проверял), поэтому корректно работающий писатель в формат эксел добавляет это "заклинание".
Я сам не спец по питону, но это можно исправлять, выполнив удаление символа 0D в DataFrame
...
Рейтинг: 0 / 0
Python - символы _x000D_ при экспорте в xlsx
    #40067050
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
x1ca4064
fraks

Ладно бы, если какой-то питоний модуль в используемой цепочке вообще бы не умел работать с переводами строк, но он переводы строк видит и сует к ним лишнее. С какой целью он это делает и в каком месте?


Вероятно, формат требует, чтобы перевод строки был 0A, в целях "совместимости" эксел допускает наличие символа 0D и _x000D_, другие программы это могут не уметь.


Никто ничего не требует.
Если сделать файл непосредственно в Excel то никаких _x000D_ он туда сам не добавляет, там обычный 0D 0A.
И все прекрасно работает, как в Excel так и при чтении файла в 1С.

Где-то унутрях питона кто-то начинает умничать и пихать в файл _x000D_ которого там не было и который там нафиг не нужен.
...
Рейтинг: 0 / 0
Python - символы _x000D_ при экспорте в xlsx
    #40067054
x1ca4064
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fraks

Если сделать файл непосредственно в Excel то никаких _x000D_ он туда сам не добавляет, там обычный 0D 0A.

К сожалению, у меня нет современного экселя, но, что 2002 эксел, что ОпенОфис сохраняют многострочный текст с разделителем 0A.
При вставке в ячейку символа 0D, он в этих пакетах сохраняется "как есть", т.е. без всяких "дополнений".

У Вас есть возможность проверить на современном экселе, как сохраняется ячейка, в которую вставили символ 0D (и 0D0A)?
Если есть, выложите файл.
...
Рейтинг: 0 / 0
Python - символы _x000D_ при экспорте в xlsx
    #40067055
x1ca4064
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
del
...
Рейтинг: 0 / 0
Python - символы _x000D_ при экспорте в xlsx
    #40067056
x1ca4064
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fraks,
Вот дискуссия , чем-то напоминающая нашу.
...
Рейтинг: 0 / 0
Python - символы _x000D_ при экспорте в xlsx
    #40067062
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще идея появилась, на счет откуда берутся _x000D_

Поле stov.descr не текстовое, а блоб.
При чтении в pandas.DataFrame его значение определяется как какой тип?
Может быть, из-за типа, или из-за наличия непечатных символов cr+lf оно в датафрейме определяется как байтовое или еще какое,
а потом, при выводе в excel оно приводится к текстовому типу, как из байтов, тогда и появляется этот _x000D_

Может быть, после загрузки данных, принудительно определить тип поля
https://www.statology.org/pandas-to-string/
и тогда его не будет корежить при экспорте.

* https://github.com/pandas-dev/pandas/blob/v0.24.2/pandas/io/excel.py#L953-L1195


Код: python
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
import pandas.compat as compat 
...
   def _value_with_fmt(self, val):
        """Convert numpy types to Python types for the Excel writers.
        Parameters
        ----------
        val : object
            Value to be written into cells
        Returns
        -------
        Tuple with the first element being the converted value and the second
            being an optional format
        """
        fmt = None

        if is_integer(val):
            val = int(val)
        elif is_float(val):
            val = float(val)
        elif is_bool(val):
            val = bool(val)
        elif isinstance(val, datetime):
            fmt = self.datetime_format
        elif isinstance(val, date):
            fmt = self.date_format
        elif isinstance(val, timedelta):
            val = val.total_seconds() / float(86400)
            fmt = '0'
        else:
            val = compat.to_str(val)

        return val, fmt



Текст самой pandas.compat.to_str найти не смог.
...
Рейтинг: 0 / 0
Python - символы _x000D_ при экспорте в xlsx
    #40067065
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
x1ca4064
fraks,
Вот дискуссия , чем-то напоминающая нашу.

Спасибо. Именно оно. Человек так же искренне недоумевает от этой херни, как и я,
а ему объясняют что в питоне никаких ошибок нет, так и должно быть :)
...
Рейтинг: 0 / 0
Python - символы _x000D_ при экспорте в xlsx
    #40067068
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
x1ca4064
fraks

Если сделать файл непосредственно в Excel то никаких _x000D_ он туда сам не добавляет, там обычный 0D 0A.

К сожалению, у меня нет современного экселя, но, что 2002 эксел, что ОпенОфис сохраняют многострочный текст с разделителем 0A.
При вставке в ячейку символа 0D, он в этих пакетах сохраняется "как есть", т.е. без всяких "дополнений".

У Вас есть возможность проверить на современном экселе, как сохраняется ячейка, в которую вставили символ 0D (и 0D0A)?
Если есть, выложите файл.


MS Office 2019
В ячейке A1 между A и B символы CR+LF
В ячейке A2 между C и D символы LF
...
Рейтинг: 0 / 0
Python - символы _x000D_ при экспорте в xlsx
    #40067070
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сам файл
...
Рейтинг: 0 / 0
Python - символы _x000D_ при экспорте в xlsx
    #40067072
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как я понял, экспорт данных из pandas в Excel делается при помощи библиотеки libxlsxwriter.

Автор этой библиотеки, jmcnamara, стоит на такой позиции:

1. перевод строки может быть только LF(0A)
2. варианты CR+LF абсолютно нелегитимны
3. если ты думаешь что это не так - смотри п.1

Исходя из этого, автор в своей библиотеке делает следующее:
если встречается CR (0D) то он его экранирует в формате _x000D_ который как бы соответствует чему-то, и Excel это хавает, но кроме него никто этим не заморачивается т.к. сам Excel такой херни не делает.

При этом есть еще и ошибка. Экранированный _x000D_ дописывается, но исходный CR (0D) так же остается, в неэкранированном виде, получается масло масляное, зачем было экранировать если неэкранированное осталось.

Есть ли такой постулат что строки в python имеют право быть только с переносом LF(0A) - я не в курсе.
Если такое есть - то jmcnamara имеет какие-то основания на свою позицию, но он этого не озвучивает.
Опять же, если есть, то пребразование CR+LF-> LF должно выполняться при любом чтении данных в строки, а это видимо не так.

Тесты, которые делает jmcnamara, с очень высокой степенью вероятности выполняются на linux а не на windows,
(судя по использванию утилиты
$ xxd test-25/xl/sharedStrings.xml)
Программа на Си, откомпиленная под linux кажись использует под понятием \n не то что программа под windows.
это сразу же делает тесты неознозначными и не применимыми ко всем случаем, в частности к windows.

Автор другой библиотеки по работе с тем же самым, проблему исправил.
https://github.com/CoreOffice/CoreXLSX/issues/83

Что остается делать.
При использовании пандаса для экспорта данных в Excel видимо придется пойти на поводу у jmcnamara и преобразовать данные внутри DataFrame, удалив оттуда CR(0D). Надеюсь тогда не будет появляться его клон в виде _x000D_.

Идиотские советы некоторых, https://stackoverflow.com/questions/36167807/access-newline-becoming-x000d
типа сделай так и поломай исходные данные, идут лесом.
Код: plsql
1.
UPDATE ImportedExcelTable SET MyField = Replace([MyField], Chr(10), Chr(13) & Chr(10));


Спасибо за участие.
...
Рейтинг: 0 / 0
Python - символы _x000D_ при экспорте в xlsx
    #40067077
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
$ xxd sharedStrings.xml
00000000: 3c3f 786d 6c20 7665 7273 696f 6e3d 2231  <?xml version="1
00000010: 2e30 2220 656e 636f 6469 6e67 3d22 5554  .0" encoding="UT
00000020: 462d 3822 2073 7461 6e64 616c 6f6e 653d  F-8" standalone=
00000030: 2279 6573 223f 3e0d 0a3c 7373 7420 786d  "yes"?>..<sst xm
00000040: 6c6e 733d 2268 7474 703a 2f2f 7363 6865  lns="http://sche
00000050: 6d61 732e 6f70 656e 786d 6c66 6f72 6d61  mas.openxmlforma
00000060: 7473 2e6f 7267 2f73 7072 6561 6473 6865  ts.org/spreadshe
00000070: 6574 6d6c 2f32 3030 362f 6d61 696e 2220  etml/2006/main"
00000080: 636f 756e 743d 2232 2220 756e 6971 7565  count="2" unique
00000090: 436f 756e 743d 2232 223e 3c73 693e 3c74  Count="2"><si><t
000000a0: 3e41 0d0a 423c 2f74 3e3c 2f73 693e 3c73  >A..B</t></si><s
000000b0: 693e 3c74 3e43 0d0a 443c 2f74 3e3c 2f73  i><t>C..D</t></s
000000c0: 693e 3c2f 7373 743e                      i></sst>

В обоих местах "0d0a"
...
Рейтинг: 0 / 0
Python - символы _x000D_ при экспорте в xlsx
    #40067636
x1ca4064
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fraks,

Попался 2007 эксел - эффект проявился: _x000d_ добавился
...
Рейтинг: 0 / 0
19 сообщений из 19, страница 1 из 1
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / Python - символы _x000D_ при экспорте в xlsx
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]