Posted: Tue Apr 17, 2012 2:30 pm Post subject: Выделить месяцы из диапазона дат
Добрый день!
Через Select-OPTIONS вводится диапазон дат, например 01.01.2012 - 14.04.2012. Как можно разбить введенный диапазон на месяца, т.е. январь (01.01.2012-31.01.2012), февраль, март, апрель (01.04.2012-14.04.2012)?
В свое время сделал так - составлям табличку дат, начиная с какого нить лохматого 2000 и заканчивая скажем +3 года к текущей дате, что нить вроде такого:
где, перед добавлением записи проверял, подходит под условия select-options. В итоге на выходе имеем табличку с датами, каждая из которых представляет собой первый день нужного нам периода.
Более красивого способа не нашел
далее исключал те даты, что не подходят под условия select-options, в итоге в табличке оставались только нужные мне периоды. Можно проверять перед добавленим
Posted: Wed Apr 18, 2012 7:50 am Post subject: Re: Выделить месяцы из диапазона дат
Tomatos wrote:
Добрый день!
Через Select-OPTIONS вводится диапазон дат, например 01.01.2012 - 14.04.2012. Как можно разбить введенный диапазон на месяца, т.е. январь (01.01.2012-31.01.2012), февраль, март, апрель (01.04.2012-14.04.2012)?
Можно свой код написать и добавить в свой ФМ и будет красиво
Код примерно такой, есть недочеты, но лень уже было дальше расписывать
Code:
SELECTION-SCREEN BEGIN OF BLOCK b_org.
SELECT-OPTIONS: so_prd FOR bkpf-budat.
SELECTION-SCREEN END OF BLOCK b_org.
DATA: l_begd TYPE d,
l_endd TYPE d,
mnth_begda(2),
mnth_endda(2),
gv_year(4),
gv_mnth(2),
n TYPE n.
DATA: BEGIN OF s_data,
l_begd TYPE d,
l_endd TYPE d,
END OF s_data,
gt_data LIKE TABLE OF s_data WITH HEADER LINE.
START-OF-SELECTION.
CLEAR: gv_mnth, gv_year.
LOOP AT so_prd.
* Проверяем что заданные даты не равны
IF so_prd-low <> so_prd-high.
* Проверяем что диапазон
IF so_prd-OPTION = 'BT'.
* Вычисляем количество месяцев
mnth_begda = so_prd-low+4(2).
mnth_endda = so_prd-high+4(2).
n = mnth_endda - mnth_begda + 1.
* Цикл по месяцам
DO n TIMES.
gv_year = so_prd-low(4).
IF gv_mnth IS INITIAL.
gv_mnth = so_prd-low+4(2).
ENDIF.
CLEAR: l_endd, l_begd.
* Заполняем начальную дату месяца
CONCATENATE gv_year gv_mnth '01' INTO l_begd.
* Находим последнюю дату месяца
CALL FUNCTION 'MM_LAST_DAY_OF_MONTHS'
EXPORTING
day_in = l_begd
IMPORTING
last_day_of_month = l_endd
EXCEPTIONS
day_in_no_date = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
По таблице MKPF выбираю документы, по дате, введенной в SELECT-OPTOINS во внутреннюю таблицу (поля MBLNR, MJAHR, BUDAT), после этого во внутренней таблице через Loop выделяю месяц в отдельное поле. В результате документы можно "разбить" по месяцам.
Age: 48 Joined: 25 Jan 2008 Posts: 580 Location: Москва
Posted: Wed Apr 18, 2012 12:39 pm Post subject:
Предлагаю свой алгоритм деления дат по периодам. Он может делить период дат (в данном случае - timestamp, но это не важно) в разрезе любых периодов, описанных в настройке вариантов финансового года (транзакция OB29)
Code:
*&---------------------------------------------------------------------*
*& Form GET_PERIODS
*&---------------------------------------------------------------------*
* Получение периодов последнего изменения документа
*----------------------------------------------------------------------*
* -->PT_ZZTIMESTAMP - входной параметр ZZTIMESTAMP
* -->PT_PERIODS - выходная таблица периодов
* -->VALUE(P_PERIV) - тип периода
*----------------------------------------------------------------------*
FORM get_periods TABLES pt_zztimestamp STRUCTURE gs_periods
pt_periods STRUCTURE gs_periods
USING value(p_periv) TYPE t009-periv.
CONSTANTS: c_first_zztimestamp TYPE likp-zztimestamp VALUE
'20051231235959',
c_first_time TYPE sy-uzeit VALUE '000000',
c_last_time TYPE sy-uzeit VALUE '235959'.
DATA: ls_periods LIKE LINE OF pt_periods,
lv_low_year TYPE t009b-bdatj,
lv_low_poper TYPE t009b-poper,
lv_high_year TYPE t009b-bdatj,
lv_high_poper TYPE t009b-poper,
lv_first_date TYPE sy-datum,
lv_last_date TYPE sy-datum,
ls_t009 TYPE t009.
FIELD-SYMBOLS: <fs_zztimestamp> LIKE LINE OF pt_zztimestamp.
DEFINE _date_to_period.
lv_last_date = <fs_zztimestamp>-&1(8).
call function 'DATE_TO_PERIOD_CONVERT'
exporting
i_date = lv_last_date
* I_MONMIT = 00
i_periv = p_periv
importing
e_buper = lv_&1_poper
e_gjahr = lv_&1_year
exceptions
input_false = 1
t009_notfound = 2
t009b_notfound = 3
others = 4.
if sy-subrc <> 0.
message id sy-msgid type sy-msgty number sy-msgno
with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
raising error_passed_to_mess_handler.
endif.
END-OF-DEFINITION.
DEFINE _period_to_date.
call function '&1_DAY_IN_PERIOD_GET'
exporting
i_gjahr = lv_low_year
* I_MONMIT = 00
i_periv = p_periv
i_poper = lv_low_poper
importing
e_date = lv_&1_date
exceptions
others = 4.
if sy-subrc <> 0.
message id sy-msgid type sy-msgty number sy-msgno
with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
raising error_passed_to_mess_handler.
endif.
END-OF-DEFINITION.
CALL FUNCTION 'GET_PERIOD_VERSION'
EXPORTING
i_periv = p_periv
* I_XTEXTS = ' '
* I_SPRAS = SY-LANGU
IMPORTING
e_t009 = ls_t009
* E_T009T =
EXCEPTIONS
OTHERS = 3.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
RAISING error_passed_to_mess_handler.
ENDIF.
IF pt_zztimestamp IS INITIAL.
"Если период изменения не заполнен, считаем равным его от начала времен
"до текущей даты
ls_periods-sign = 'I'.
ls_periods-option = 'BT'.
CONCATENATE sy-datum c_last_time INTO ls_periods-high.
APPEND ls_periods TO pt_zztimestamp.
ENDIF.
REFRESH pt_periods.
LOOP AT pt_zztimestamp ASSIGNING <fs_zztimestamp>.
ls_periods = <fs_zztimestamp>.
IF <fs_zztimestamp>-low IS INITIAL. "Начальная дата не задана
ls_periods-high = c_first_zztimestamp.
APPEND ls_periods TO pt_periods.
lv_first_date = c_first_zztimestamp(8).
ADD 1 TO lv_first_date.
CONCATENATE lv_first_date c_first_time INTO <fs_zztimestamp>-low.
ENDIF.
_date_to_period: low, high.
* Цикл по периодам
WHILE lv_low_year < lv_high_year OR ( lv_low_year = lv_high_year
AND lv_low_poper <= lv_high_poper ).
_period_to_date: first, last.
ls_periods-sign = 'I'.
ls_periods-option = 'BT'.
IF sy-index > 1 AND lv_first_date >= <fs_zztimestamp>-low.
CONCATENATE lv_first_date c_first_time INTO ls_periods-low.
ELSE.
ls_periods-low = <fs_zztimestamp>-low.
ENDIF.
IF lv_low_year <> lv_high_year OR lv_low_poper <> lv_high_poper.
CONCATENATE lv_last_date c_last_time INTO ls_periods-high.
ELSE.
ls_periods-high = <fs_zztimestamp>-high.
ENDIF.
APPEND ls_periods TO pt_periods.
IF lv_low_poper = ls_t009-anzbp.
lv_low_poper = '001'.
ADD 1 TO lv_low_year.
ELSE.
ADD 1 TO lv_low_poper.
ENDIF.
ENDWHILE.
ENDLOOP.
ENDFORM. " GET_PERIODS
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
All product names are trademarks of their respective companies. SAPNET.RU websites are in no way affiliated with SAP AG. SAP, SAP R/3, R/3 software, mySAP, ABAP, BAPI, xApps, SAP NetWeaver and any other are registered trademarks of SAP AG. Every effort is made to ensure content integrity. Use information on this site at your own risk.