Текущее время: Сб, авг 09 2025, 23:43

Часовой пояс: UTC + 3 часа


Правила форума


ВНИМАНИЕ!

Вопросы по SAP Query и Quick View - сюда



Начать новую тему Ответить на тему  [ Сообщений: 24 ]  На страницу 1, 2  След.
Автор Сообщение
 Заголовок сообщения: Остатки на складе
СообщениеДобавлено: Ср, окт 07 2015, 13:08 
Специалист
Специалист

Зарегистрирован:
Ср, окт 07 2015, 12:36
Сообщения: 124
Всем добрый день.

Я пока ещё только новичок в программировании, хотел бы уточнить один момент. Он, скорее всего, элементарный, но на форуме ничего похожего не нашёл. Вообщем смысл кода ниже в том, что когда пользователь задает на селекционном экране данные (завод, склад, дату, материал). На выходе он должен получить остаток этого материала на складе на указанную дату. Да, я знаю, что есть стандартная программа RM07MLBD, где всё это реализовано на порядок лучше и сложнее, но я пока просто тренируюсь и не могу понять, почему ничего не выводится на экран. Вернее, судя по тому, что компилятор не ругается - просто таблица пустая и выводить нечего, но почему она пустая, если все условия выполняются и в таблицах данные есть - проверял через se16. И да, скорее всего, код выглядит очень коряво - буду благодарен конструктивным замечаниям =)

Code:
REPORT zlab_1.

TABLES: mara, makt, mard, mkpf, mseg.

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.

DATA: p_material  LIKE mara-matnr,
      p_warehouse LIKE mard-lgort,
      wa_mseg     LIKE mseg OCCURS 0 WITH HEADER LINE,
      wa_mard     LIKE mard OCCURS 0 WITH HEADER LINE.

PARAMETERS: p_data  LIKE sy-datum DEFAULT sy-datum OBLIGATORY,
            p_plant LIKE mard-werks.

SELECT-OPTIONS: s_mat FOR p_material OBLIGATORY,
                s_wh  FOR p_warehouse.

SELECTION-SCREEN END OF BLOCK b1.

START-OF-SELECTION.

  SELECT matnr werks lgort labst
            FROM mard INTO CORRESPONDING FIELDS OF wa_mard
            WHERE matnr IN s_mat
            AND lgort IN s_wh
            AND werks EQ p_plant.
  ENDSELECT.

LOOP AT wa_mard.
    LOOP AT wa_mseg.
      IF wa_mseg-budat_mkpf GE p_data.
        IF wa_mard-matnr EQ wa_mseg-matnr AND wa_mard-werks EQ wa_mseg-werks AND wa_mard-lgort EQ wa_mseg-lgort.
          IF wa_mseg-shkzg EQ 'H'.
            ADD wa_mseg-menge TO wa_mard-labst.
          ELSEIF wa_mseg-shkzg EQ 'S'.
            SUBTRACT wa_mseg-menge FROM wa_mard-labst.
          ENDIF.
        ENDIF.
      ENDIF.
    ENDLOOP.
  ENDLOOP.

LOOP AT wa_mard.
WRITE: /  wa_mard-matnr,
               wa_mard-lgort,
               wa_mard-labst.
ENDLOOP.


Спасибо.


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Остатки на складе
СообщениеДобавлено: Ср, окт 07 2015, 13:17 
Почетный гуру
Почетный гуру
Аватара пользователя

Зарегистрирован:
Чт, авг 19 2004, 17:37
Сообщения: 1962
Откуда: Москва
Пол: Мужской
SELECT matnr werks lgort labst
FROM mard INTO CORRESPONDING FIELDS OF TABLE wa_mard

_________________
"For all entries" не в SAP-ах, "for all entries" в головах! :)


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Остатки на складе
СообщениеДобавлено: Ср, окт 07 2015, 14:27 
Специалист
Специалист

Зарегистрирован:
Ср, окт 07 2015, 12:36
Сообщения: 124
Parazit написал:
SELECT matnr werks lgort labst
FROM mard INTO CORRESPONDING FIELDS OF TABLE wa_mard


Да, благодарю. Это помогло... А что получается если мы не пишем TABLE? Почему компилятор не выдавал сообщений об ошибке?


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Остатки на складе
СообщениеДобавлено: Ср, окт 07 2015, 14:48 
Почетный гуру
Почетный гуру
Аватара пользователя

Зарегистрирован:
Чт, авг 19 2004, 17:37
Сообщения: 1962
Откуда: Москва
Пол: Мужской
boreich написал(а):
Parazit написал:
SELECT matnr werks lgort labst
FROM mard INTO CORRESPONDING FIELDS OF TABLE wa_mard


Да, благодарю. Это помогло... А что получается если мы не пишем TABLE? Почему компилятор не выдавал сообщений об ошибке?

Потому что это не ошибка. Нужно понимать, что при данном объявлении wa_mard существует ДВЕ переменные с одинаковым именем, одна структура (т.н. header line) и одна внутренняя таблица - ноухау SAP.
Без TABLE данные по одной записи ложились в структуру в цикле между Select и EndSelect, каждый раз затирая предыдущее значение. В принципе можно было сделать и так:
Code:
Select ...
  Append wa_mard to wa_mard.
EndSelect.

Специально написал через "to", чтобы было понятней, что первая wa_mard структура, а вторая таблица. Можно просто Append wa_mard.

_________________
"For all entries" не в SAP-ах, "for all entries" в головах! :)


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Остатки на складе
СообщениеДобавлено: Ср, окт 07 2015, 15:19 
Специалист
Специалист

Зарегистрирован:
Ср, окт 07 2015, 12:36
Сообщения: 124
Понятно, спасибо. Да, нашёл теперь... невнимательно прочитал про эту внутреннюю таблицу...


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Остатки на складе
СообщениеДобавлено: Ср, окт 07 2015, 15:56 
Специалист
Специалист

Зарегистрирован:
Ср, окт 07 2015, 12:36
Сообщения: 124
А если теперь это через alv grid вывести, то там есть метод set_table_for_first_display с обязательным параметром в секции "CHANGING" it_outtab. Я так понимаю, что в нём мы указываем что, собственно, хотим вывести на экран, верно? Только ни mard, ни wa_mard компилятору не нравятся:
"MARD" имеет тип, несовместимый с формальным параметром "IT_OUTTAB". Так что ему там нужно указать? Или можно как то принудительно привести тип к нужному?


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Остатки на складе
СообщениеДобавлено: Ср, окт 07 2015, 16:01 
Почетный гуру
Почетный гуру
Аватара пользователя

Зарегистрирован:
Чт, авг 19 2004, 17:37
Сообщения: 1962
Откуда: Москва
Пол: Мужской
boreich написал(а):
А если теперь это через alv grid вывести, то там есть метод set_table_for_first_display с обязательным параметром в секции "CHANGING" it_outtab. Я так понимаю, что в нём мы указываем что, собственно, хотим вывести на экран, верно? Только ни mard, ни wa_mard компилятору не нравятся:
"MARD" имеет тип, несовместимый с формальным параметром "IT_OUTTAB". Так что ему там нужно указать? Или можно как то принудительно привести тип к нужному?

Компилятор пытается по контексту определить что такое wa_mard, структура или таблица. Если бы это был, например, вызов ФМ через параметры TABLES, он бы понял, что это таблица. В случае CHANGING он понимает wa_mard как структуру. Чтобы явно указать, что это таблица, используйте синтаксис wa_mard[].

_________________
"For all entries" не в SAP-ах, "for all entries" в головах! :)


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Остатки на складе
СообщениеДобавлено: Ср, окт 07 2015, 16:10 
Почетный гуру
Почетный гуру
Аватара пользователя

Зарегистрирован:
Чт, авг 19 2004, 17:37
Сообщения: 1962
Откуда: Москва
Пол: Мужской
Общий совет: избавляйтесь от использования header line, т.к. это устаревающий формат. Например, в объектных классах он вообще запрещён. Используйте раздельные переменные для структуры записи и таблицы.
Code:
Data:
  lt_MARD type standard table of MARD,
  wa_MARD type MARD.
Select *
  into table lt_MARD
  from MARD  ...

Loop at lt_MARD into wa_MARD.
...
EndLoop.

_________________
"For all entries" не в SAP-ах, "for all entries" в головах! :)


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Остатки на складе
СообщениеДобавлено: Ср, окт 07 2015, 16:12 
Специалист
Специалист

Зарегистрирован:
Ср, окт 07 2015, 12:36
Сообщения: 124
Parazit написал:
Компилятор пытается по контексту определить что такое wa_mard, структура или таблица. Если бы это был, например, вызов ФМ через параметры TABLES, он бы понял, что это таблица. В случае CHANGING он понимает wa_mard как структуру. Чтобы явно указать, что это таблица, используйте синтаксис wa_mard[].

Да, теперь скомпилилось, но при запуске выдаёт "Невозможно определить каталог полей." и выкидывает вообще в EasyAccess меню... Я так понимаю, что в ПБО нужно как то дополнительно инициализировать эту таблицу?


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Остатки на складе
СообщениеДобавлено: Ср, окт 07 2015, 16:16 
Почетный гуру
Почетный гуру
Аватара пользователя

Зарегистрирован:
Чт, авг 19 2004, 17:37
Сообщения: 1962
Откуда: Москва
Пол: Мужской
boreich написал(а):
Parazit написал:
Компилятор пытается по контексту определить что такое wa_mard, структура или таблица. Если бы это был, например, вызов ФМ через параметры TABLES, он бы понял, что это таблица. В случае CHANGING он понимает wa_mard как структуру. Чтобы явно указать, что это таблица, используйте синтаксис wa_mard[].

Да, теперь скомпилилось, но при запуске выдаёт "Невозможно определить каталог полей." и выкидывает вообще в EasyAccess меню... Я так понимаю, что в ПБО нужно как то дополнительно инициализировать эту таблицу?

Параметр I_STRUCTURE_NAME = 'MARD' метода SET_TABLE_FOR_FIRST_DISPLAY.

_________________
"For all entries" не в SAP-ах, "for all entries" в головах! :)


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Остатки на складе
СообщениеДобавлено: Ср, окт 07 2015, 16:21 
Специалист
Специалист

Зарегистрирован:
Ср, окт 07 2015, 12:36
Сообщения: 124
Цитата:
Параметр I_STRUCTURE_NAME = 'MARD' метода SET_TABLE_FOR_FIRST_DISPLAY.

Да, теперь работает. Спасибо вам большое за помощь - за последние пару часов узнал больше, чем за прошедшие пару дней =) А не подскажите, что можно почитать новичку по всем этим делам... Нашёл вот курсы ВС400, ВС401... но там многие вещи как то пропускаются...


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Остатки на складе
СообщениеДобавлено: Ср, окт 07 2015, 16:34 
Почетный гуру
Почетный гуру
Аватара пользователя

Зарегистрирован:
Чт, авг 19 2004, 17:37
Сообщения: 1962
Откуда: Москва
Пол: Мужской
boreich написал(а):
Цитата:
Параметр I_STRUCTURE_NAME = 'MARD' метода SET_TABLE_FOR_FIRST_DISPLAY.

Да, теперь работает. Спасибо вам большое за помощь - за последние пару часов узнал больше, чем за прошедшие пару дней =) А не подскажите, что можно почитать новичку по всем этим делам... Нашёл вот курсы ВС400, ВС401... но там многие вещи как то пропускаются...

Самая расхожая книга Разработка приложений для SAP R/3 на языке ABAP/4 Р.Кречмер, В.Вайс.
Также смотрите тему Материалы по программированию в SAP
От себя добавлю, обязательно изучайте SQL, поможет избежать многих бед, которыми страдают даже опытные абаперы.

_________________
"For all entries" не в SAP-ах, "for all entries" в головах! :)


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Остатки на складе
СообщениеДобавлено: Ср, окт 07 2015, 16:53 
Специалист
Специалист

Зарегистрирован:
Ср, окт 07 2015, 12:36
Сообщения: 124
Parazit написал:
Самая расхожая книга Разработка приложений для SAP R/3 на языке ABAP/4 Р.Кречмер, В.Вайс.
Также смотрите тему Материалы по программированию в SAP
От себя добавлю, обязательно изучайте SQL, поможет избежать многих бед, которыми страдают даже опытные абаперы.

Спасибо, буду учить :)


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Остатки на складе
СообщениеДобавлено: Сб, окт 10 2015, 13:08 
Специалист
Специалист

Зарегистрирован:
Ср, окт 07 2015, 12:36
Сообщения: 124
Ещё раз здравствуйте. Чтобы не плодить новых тем, решил написать в этой. Немного отрефакторил программу, которая представлена в первом посте. Получилось примерно вот так:

Селекционный экран:
Code:
REPORT zlab_1.

TABLES: mara, makt, mard, mkpf, mseg.

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.

TYPES: BEGIN OF st_mard,
         matnr TYPE mard-matnr,
         werks TYPE mard-werks,
         lgort TYPE mard-lgort,
         labst TYPE mard-labst,
       END OF st_mard.

TYPES: BEGIN OF st_mseg,
         matnr      TYPE mseg-matnr,
         werks      TYPE mseg-werks,
         lgort      TYPE mseg-lgort,
         budat_mkpf TYPE mseg-budat_mkpf,
         shkzg      TYPE mseg-shkzg,
         menge      TYPE mseg-menge,
       END OF st_mseg.

DATA: p_material    LIKE mara-matnr,
      p_warehouse   LIKE mard-lgort,
      lt_mseg       TYPE STANDARD TABLE OF st_mseg,
      lt_mard       TYPE STANDARD TABLE OF st_mard,
      wa_mseg       TYPE st_mseg,
      wa_mard       TYPE st_mard,
      container_ref TYPE REF TO cl_gui_custom_container,
      grid_ref      TYPE REF TO cl_gui_alv_grid.

PARAMETERS: p_data  LIKE sy-datum DEFAULT sy-datum OBLIGATORY,
            p_plant LIKE mard-werks.

SELECT-OPTIONS: s_mat FOR p_material OBLIGATORY,
                s_wh  FOR p_warehouse.

SELECTION-SCREEN END OF BLOCK b1.

Здесь объявляются структуры st_mard, st_mseg с нужными мне полями, далее внутренние таблицы lt_mseg, lt_mard и, соответствующие им, рабочие области wa_mseg, wa_mard.
Хотел бы уточнить, насколько я хорошо использую здесь концепцию "внутренняя таблица - рабочая область"? Возможно есть более оптимальные варианты...
Затем перенос данных в эти таблицы из базы:
Code:
START-OF-SELECTION.

  SELECT * FROM mard INTO CORRESPONDING FIELDS OF TABLE lt_mard
      WHERE matnr IN s_mat
      AND lgort IN s_wh
      AND werks EQ p_plant.

  SELECT * FROM mseg INTO CORRESPONDING FIELDS OF TABLE lt_mseg
      WHERE matnr IN s_mat
      AND lgort IN s_wh
      AND werks EQ p_plant.

Здесь, насколько я знаю, всё должно быть нормально (здесь по субъективным ощущениям, оператор * работает немного быстрее, чем перечисление всех необходимых полей, как это ни странно).
Далее идёт выборка нужных мне данных и основной смысл программы - показ остатков на складе на необходимую дату:
Code:
LOOP AT lt_mard INTO wa_mard.
    LOOP AT lt_mseg INTO wa_mseg.
      IF wa_mseg-budat_mkpf GE p_data.
        IF  wa_mard-matnr EQ wa_mseg-matnr
        AND wa_mard-werks EQ wa_mseg-werks
        AND wa_mard-lgort EQ wa_mseg-lgort.
          IF wa_mseg-shkzg EQ 'H'.
            ADD wa_mseg-menge TO wa_mard-labst.
          ELSEIF wa_mseg-shkzg EQ 'S'.
            SUBTRACT wa_mseg-menge FROM wa_mard-labst.
          ENDIF.
        ENDIF.
      ENDIF.
    ENDLOOP.
    WRITE: /  wa_mard-matnr,
                   wa_mard-lgort,
                   wa_mard-labst.
  ENDLOOP.

Здесь, думаю, выглядит не очень, но работает... write-ом на экран выводится корректная информация. Но при попытке сделать вывод через alv возникли некоторые трудности. Остаток кода в основной программе выглядит так:
Code:
CALL SCREEN 100.

INCLUDE zlab_1_pbo_0100.

А вот содержание модуля PBO(zlab_1_pbo_0100):
Code:
MODULE create_container_and_alv OUTPUT.
  IF container_ref IS INITIAL.
    CREATE OBJECT container_ref
      EXPORTING
        container_name = 'CC_ALV'.

    CREATE OBJECT grid_ref
      EXPORTING
        i_parent = container_ref.

    CALL METHOD grid_ref->set_table_for_first_display
      EXPORTING
        i_structure_name              = 'ST_MARD'
      CHANGING
        it_outtab                     = lt_mard[]
  ENDIF.
ENDMODULE.

Если всё это запустить, то компилятор не ругается, но потом, выдаёт исключение "NO_FIELDCATALOG_AVAILABLE" triggered. Я так понимаю, дело в том, что не указан необязательный параметр it_fieldcatalog в секции CHANGING. Только дело в том, что программа, которую мне помог привести в рабочий вид товарищ Parazit (за что ему большое человеческое спасибо), приведённая несколько сообщений назад работала и выводила alv grid (правда всё равно выводилось не совсем то, что ожидалось) и без этого параметра. Изменилось, по сути, только то, что я добавил кастомные структуры в код. Но теперь непонятно, что нужно указать в этом it_fieldcatalog-е. Но ещё одна проблема в том, что в гриде выводится неизменённая версия таблицы mard, а через write всё работает хорошо... Тоже не совсем понятно, почему.


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Остатки на складе
СообщениеДобавлено: Сб, окт 10 2015, 14:54 
Почетный гуру
Почетный гуру
Аватара пользователя

Зарегистрирован:
Чт, авг 19 2004, 17:37
Сообщения: 1962
Откуда: Москва
Пол: Мужской
Начну с конца.

LOOP AT lt_mard INTO wa_mard - Копирует очередную запись из таблицы в структуру wa_mard.
ADD wa_mseg-menge TO wa_mard-labst - Изменяет значение в структуре wa_mard.
Осталось только сохранить изменения структуры в запись таблицы - Modify lt_mard from wa_mard.

Когда Вы в ALV выводили внутреннюю таблицу, которая на 100% соответствует таблице словаря MARD, то можно было просто указать имя структуры словаря через параметр I_STRUCTURE_NAME. ALV сам запрашивал информацию из словаря и формировал внутри Field Catalog - внутреннюю таблицу с описанием полей.
Поскольку теперь Вы описали локальную структуру, придется самому заполнять Field Catalog и передавать его через парамет IT_FIELDCATALOG. Соответственно I_STRUCTURE_NAME уже не нужен.

Когда у Вас всё заработает, рекомендую полностью всё переделать, начиная с выборки данных. Объедините оба запроса в один через JOIN и кладите результат в одну внутреннюю таблицу. Также советую в этом Select-е сделать агрегирование (т.е. суммирование) , используя GROUP BY и SUM( имя_поля ). В результате у Вас и выборка будет быстрее, и по сети будет передаваться меньший объем данных, и внутренняя таблица будет отнимать меньше памяти у сервера приложений.
Во внутренней таблице будут лежать уже готовые обороты за весь период по дебету и кредиту, останется только рассчитать сальдо.

_________________
"For all entries" не в SAP-ах, "for all entries" в головах! :)


Принять этот ответ
Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 24 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: Ahrefs [Bot], Google [Bot]


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB