Текущее время: Чт, июн 26 2025, 13:57

Часовой пояс: 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 часа


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

Сейчас этот форум просматривают: нет зарегистрированных пользователей


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

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