Выгрузка данных из SAP в различных кодировках WIN1251/KOI8 и т.д.

Автор Uukrul, Квітень 16, 2012, 10:26:26 ПП

Попередня тема - Наступна тема

0 Користувачі і 1 Гість дивляться цю тему.

Uukrul

Для программ работающих на сервере приложений, выгрузка данных обычно выполняется через операции OPEN DATASET / CLOSE DATASET и тут встает проблема как выгрузить данные в нужной кодировке для кириллических букв. Системы обычно сейчас юникодные и значит при выгрузке кодировка будет скорее всего UTF-8, но тут встал вопрос что файл должен быть выгружен в кодировке WIN1251 и это файл формата XML. На форумах есть разные варианты, в основном они касаются выгрузки на фонтэнд, для фоновых процессов был найден вариант да и тот предлагал использовать выгрузку в XML со схемой XML. Загвоздка оказалась в том, что я XML не знаю, а его схему тем более. Сформировать файл в заданной XML структуре во внутреннюю таблицу не вопрос, а вот как дальше ее выгрузить?! Короче покопавшись в справке SAP предлагает следующий вариант.

Потребуются следующие переменные:

  DATA: hx(2) TYPE x VALUE '0D0A',   "Перевод строки для WIN1251
        l_str TYPE string,
        g_buffer TYPE xstring,         "Байтовый буфер в кодировке WIN1251
        encoding TYPE string,          "Строка кодировки
        codepage_n TYPE cpcodepage,    "Кодовая страница к кодировке число
        codepage_c TYPE abap_encoding, "Кодовая страница как строка
        cvto_win TYPE REF TO cl_abap_conv_out_ce.

DATA: BEGIN OF gt_xml_cskt OCCURS 10,
  line type string,
END OF gt_xml_cskt.

Для начала получим саповскую кодовую страницу для кодировки WIN1251, для этого есть специальная функция:

  encoding = 'windows-1251'.
  CALL FUNCTION 'SCP_CODEPAGE_BY_EXTERNAL_NAME'
    EXPORTING
      external_name = encoding
    IMPORTING
      sap_codepage  = codepage_n
    EXCEPTIONS
      not_found     = 1
      OTHERS        = 2.

Чтобы узнать вот этот вот код windows-1251, можно просмотреть таблицу TCP00A и там познавательно можно посмотреть соответствие кодовых таблиц SAP общепринятым кодировкам типа KOI8 и т.д. Так что на выходе получаем кодовую таблицу SAP, для кодировки WIN1251 что будет равно 1504. Конечно можно сразу подставлять дальше код 1504, но мы же пишем правильно и на все случаи  8). Далее создадим класс который будет производить конвертацию данных из UTF-8 в нашу WIN1251, точнее 1504. Проблема тут в том, что предыдущая функция возвращает кодировку в типе NUM, а класс требует передачи параметра типа CHAR, поэтому заводим еще одну переменную, которую и передаем в класс в качестве кодовой страницы. Класс CL_ABAP_CONV_OUT_CE:

  codepage_c = codepage_n.
  CALL METHOD cl_abap_conv_out_ce=>create
    EXPORTING
      encoding = codepage_c
    RECEIVING
      conv     = cvto_win.

Далее очищаем принимающий буфер для нашего экземпляра класса

      cvto_win->reset( ).

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

     LOOP AT gt_xml_cskt.
        CALL METHOD cvto_win->write
          EXPORTING
            data = gt_xml_cskt-line.
        CALL METHOD cvto_win->write
          EXPORTING
            data = hx.
      ENDLOOP.

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

    OPEN DATASET g_file_cost FOR OUTPUT IN BINARY MODE.

Записываем буфер в файл:

      TRANSFER cvto_win->get_buffer( ) TO g_file_cost.
     
После чего закрываем файл:

      CLOSE DATASET g_file_cost.

Все данные в файле будут в кодировке WIN1251. Так сказать быстро и просто.

PS: Во внутренней таблице gt_xml_cskt данные записаны типа в таком виде, каждая строка отдельная строка внутренней таблицы:

<?xml version="1.0" encoding="windows-1251" ?>
<MVZ date_time="16.04.2012 23:21:02"  unit_count="ОАО «Пупкин и КО»">
<unit Index="1 ">
<Kod>3000200001</Kod>
<Name>Отдел передачи данны</Name>
<Date>31.12.9999</Date>
</unit>
</MVZ>

Calm

Огромное человеческое спасибо! :)

Только не прокатывает по синтаксису
TRANSFER cvto_win->get_buffer( ) TO g_file_cost.

Сап хочет что-то вроде
DATA: lv_xstring TYPE xstring.
...
CALL METHOD lo_win_coder->get_buffer
      RECEIVING
        buffer = lv_xstring.

Uukrul

Цитата: Calm від Вересень 11, 2015, 11:24:39 ДП
Сап хочет что-то вроде

CALL METHOD lo_win_coder->get_buffer
      RECEIVING
        buffer = lv_xstring.

К сожалению с версии 7.0х, по версию 7.3х а уж тем более в версии 7.4х очень много чего изменилось в абапе. Как минимум практически нет переносимости кода с верхних версий вниз и чем дальше, тем так сказать версии разбегаются. Абап 7.4х поверьте вещь и писать на нем намного удобнее и понял я это, когда пришлось недавно делать программу обратно совместимой для 7.0х, точнее она должна была параллельно работать в двух разных системах 7.0х и 7.4х. Поверьте, очень сильно ругался, пока делал. Так что чем дальше, тем более странные синтаксисы операторов вы будете видеть на этом форуме  8)

PS: Вообще у меня тут есть мысль, по поводу абапа 7.4х пописать о различиях и удобствах, но все никак руки не доходят.

Calm

Не очень понял Ваш пост про версии.
Я работаю в системе с абап 7.40. И код 2012 года в нем должен работать по-любому.


Еще раз Вам спасибо :)

Uukrul

Цитата: Calm від Вересень 30, 2015, 11:37:45 ДП
Я работаю в системе с абап 7.40. И код 2012 года в нем должен работать по-любому.
Если честно, я не помню когда вышло ядро 7.40, но к примеру абап 7.40 отличается от ABAP 7.31 и очень сильно отличается от ядер абапа 7.01 / 7.02. Поэтому работать по любому, я бы не взялся утверждать. Точнее смотря как вы пишете... и что пишете.