Как преобразовать извлечение SAP .txt в файл .csv - PullRequest
0 голосов
/ 07 октября 2019

У меня есть файл .txt, как в приведенном ниже примере. Я хотел бы преобразовать его в таблицу .csv, но я не добился большого успеха.

Mack3                                            Line Item Journal                                        Time 14:22:33     Date  03.10.2015
Panteni    Ledger 1L                                                                                    TGEPIO00/CANTINAOAS Page      20.001
--------------------------------------------------------------------------------------------------------------------------------------------
|    Pstng Date|Entry Date|DocumentNo|Itm|Doc..Date |BusA|PK|SG|Sl|Account   |User Name   |LCurr|      Amount in LC|Tx|Assignment        |S|
|------------------------------------------------------------------------------------------------------------------------------------------|
|    07.01.2014|07.02.2014|4919005298| 36|07.01.2019|    |81|  |  |60532640  |tARFooWMOND |EUR  |             0,85 |  |20140107          | |
|    07.01.2014|07.02.2014|4919065298| 29|07.01.2019|    |81|  |  |60532640  |tARFooWMOND |EUR  |             2,53 |  |20140107          | |
|    07.01.2014|07.02.2014|4919235298| 30|07.01.2019|    |81|  |  |60532640  |tARFooWMOND |EUR  |            30,00 |  |20140107          | |
|    07.01.2014|07.02.2014|4119005298| 32|07.01.2019|    |81|  |  |60532640  |tARFooWMOND |EUR  |             1,00 |  |20140107          | |
|    07.01.2014|07.02.2014|9019005298| 34|07.01.2019|    |81|  |  |60532640  |tARFooWMOND |EUR  |            11,10 |  |20140107          | |
|------------------------------------------------------------------------------------------------------------------------------------------|

Данный файл является структурой отчета SAP. Практикуясь с python и просматривая другие посты, я нашел этот код:

    with open('file.txt', 'rb') as f_input:
        for line in filter(lambda x: len(x) > 2 and x[0] == '|' and x[1].isalpha(), f_input):
            header = [cols.strip() for cols in next(csv.reader(StringIO(line), delimiter='|', skipinitialspace=True))][1:-1]
            break
    with open('file.txt', 'rb') as f_input, open(str(ii + 1) + 'output.csv', 'wb') as f_output:
        csv_output = csv.writer(f_output)
        csv_output.writerow(header)
        for line in filter(lambda x: len(x) > 2 and x[0] == '|' and x[1] != '-' and not x[1].isalpha(), f_input):
            csv_input = csv.reader(StringIO(line), delimiter='|', skipinitialspace=True)
            csv_output.writerow(csv_input)

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

Есть ли какое-нибудь возможное решение?

1 Ответ

0 голосов
/ 07 октября 2019

Ваш входной файл может рассматриваться как CSV, как только мы отфильтруем несколько строк, а именно те, которые не начинаются с символа трубы '|', за которым следует пробел ' ', что оставляет нас с этим:

|    Pstng Date|Entry Date|DocumentNo|Itm|Doc..Date |BusA|PK|SG|Sl|Account   |User Name   |LCurr|      Amount in LC|Tx|Assignment        |S|
|    07.01.2014|07.02.2014|4919005298| 36|07.01.2019|    |81|  |  |60532640  |tARFooWMOND |EUR  |             0,85 |  |20140107          | |
|    07.01.2014|07.02.2014|4919065298| 29|07.01.2019|    |81|  |  |60532640  |tARFooWMOND |EUR  |             2,53 |  |20140107          | |
|    07.01.2014|07.02.2014|4919235298| 30|07.01.2019|    |81|  |  |60532640  |tARFooWMOND |EUR  |            30,00 |  |20140107          | |
|    07.01.2014|07.02.2014|4119005298| 32|07.01.2019|    |81|  |  |60532640  |tARFooWMOND |EUR  |             1,00 |  |20140107          | |
|    07.01.2014|07.02.2014|9019005298| 34|07.01.2019|    |81|  |  |60532640  |tARFooWMOND |EUR  |            11,10 |  |20140107          | |

Ваш вывод в основном пуст, потому что эта проверка x[1].isalpha() никогда не верна для этих данных. Символ в позиции 1 в каждой строке всегда является пробелом, а не алфавитом.

Нет необходимости открывать входной файл несколько раз, мы можем читать, фильтровать и записывать в выходной файл за один раз:

import csv

ii = 0

with open('file.txt', 'r', encoding='utf8', newline='') as f_input, \
     open(str(ii + 1) + 'output.csv', 'w', encoding='utf8', newline='') as f_output:

    input_lines = filter(lambda x: len(x) > 2 and x[0] == '|' and x[1] == ' ', f_input)

    csv_input = csv.reader(input_lines, delimiter='|')
    csv_output = csv.writer(f_output)

    for row in csv_input:
        csv_output.writerow(col.strip() for col in row[1:-1])

Примечания:

  • Вы должны не использовать двоичный режим при чтении текстовых файлов. Используйте режимы r и w соответственно и явно объявите кодировку файла. Выберите кодировку, подходящую для ваших файлов.
  • Для работы с модулем csv откройте файлы с помощью newline='' (что позволяет модулю csv выбрать правильные окончания строк)
  • Вы можете заключить несколько файлов в операторы with, используя \ в конце строки.
  • StringIO совершенно не нужно.
  • Я не используюskipinitialspace=True потому что в некоторых столбцах также есть пробелы в конце. Поэтому я вызываю .strip() вручную для каждого значения при записи строки.
  • [1:-1] необходимо, чтобы избавиться от лишних пустых столбцов (до первого и после последнего | ввход)

Вывод выглядит следующим образом

Pstng Date,Entry Date,DocumentNo,Itm,Doc..Date,BusA,PK,SG,Sl,Account,User Name,LCurr,Amount in LC,Tx,Assignment,S
07.01.2014,07.02.2014,4919005298,36,07.01.2019,,81,,,60532640,tARFooWMOND,EUR,"0,85",,20140107,
07.01.2014,07.02.2014,4919065298,29,07.01.2019,,81,,,60532640,tARFooWMOND,EUR,"2,53",,20140107,
07.01.2014,07.02.2014,4919235298,30,07.01.2019,,81,,,60532640,tARFooWMOND,EUR,"30,00",,20140107,
07.01.2014,07.02.2014,4119005298,32,07.01.2019,,81,,,60532640,tARFooWMOND,EUR,"1,00",,20140107,
07.01.2014,07.02.2014,9019005298,34,07.01.2019,,81,,,60532640,tARFooWMOND,EUR,"11,10",,20140107,
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...