Posted: Thu Jun 16, 2011 12:11 pm Post subject: выгрузка DBF файла на сервер приложений
Здравствуйте уважаемые коллеги. Возникла задача выгружать DBF файл на сервер приложений с помощью OPEN DATASET... Стандартного решения не нашел и поэтому взял процедуру из ФМ GUI_DOWNLOAD которая срабатывает при выгрузке в формате DBF. На ее основе слепил собственный ФМ.
Бинарный массив во внутренней таблице prc_hex_tab получается вроде бы то что надо, но после выгрузки через OPEN DATASET в конец файла дописываются непонятные байты из-за которых DBF-ка читается некорректно. Не могу понять как от них избавиться?
Ниже код ФМ и программа для его тестирования в которой файл test1.dbf выгружается локально с помощью стандартного GUI_DOWNLOAD а test2.dbf удаленно через мой ФМ. Версия системы 6.0.
Нормальный файл test1.dbf
Файл test2.dbf с непонятными байтами
Код ФМ:
Code:
FUNCTION zdbf_download.
*"----------------------------------------------------------------------
*"*"Локальный интерфейс:
*" IMPORTING
*" REFERENCE(FILENAME) TYPE STRING
*" REFERENCE(ENCODING) TYPE CHAR20
*" TABLES
*" DATA_TAB
*" FIELD_TAB
*"----------------------------------------------------------------------
*&---------------------------------------------------------------------*
*& Form dbf_download
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->PAR_DATA_TAB text
* -->PAR_FIELD_NAMES text
* -->PAR_FILENAME text
* -->PAR_COL_SELECT text
* -->PAR_COL_SELECT_MASK text
* -->PAR_ENCODING text
* -->PAR_IGNORE_CERR text
* -->PAR_REPLACEMENT_CHAR text
*----------------------------------------------------------------------*
FORM dbf_download TABLES par_data_tab
par_field_names
USING
par_filename TYPE string
par_col_select TYPE c
par_col_select_mask TYPE c
par_encoding TYPE abap_encoding
par_ignore_cerr TYPE abap_bool
par_replacement_char TYPE abap_repl.
DATA: prc_lines_count TYPE i,
prc_all_columns_count TYPE i, " columns including invalid types
prc_columns_count TYPE i, " columns including valid types
prc_column_idx TYPE i,
prc_data_type TYPE c,
prc_output_length TYPE i,
prc_dpts_length TYPE i,
prc_column_name(256) TYPE c,
prc_column_name_str TYPE string,
prc_column_value(256) TYPE c,
prc_column_value_str TYPE string,
prc_dbf_data_type TYPE c,
prc_table_type TYPE c,
prc_output_string TYPE xstring.
DESCRIBE TABLE par_data_tab LINES prc_lines_count.
DESCRIBE FIELD par_data_tab TYPE prc_table_type
COMPONENTS prc_all_columns_count.
*----------------------------------------------------------------------*
*** Convert par_replacement_char into ABAP character number
*----------------------------------------------------------------------*
DATA: prc_conv TYPE REF TO cl_abap_conv_out_ce,
prc_xstr_no TYPE xstring,
prc_i_no TYPE i,
prc_sapno TYPE cpcharno,
prc_space TYPE string.
TRY.
CALL METHOD cl_abap_conv_out_ce=>create
EXPORTING
encoding = '4000'
RECEIVING
conv = prc_conv.
CATCH cx_parameter_invalid_range .
MESSAGE ID 'FES' TYPE 'E' NUMBER '023' RAISING unknown_error.
CATCH cx_sy_codepage_converter_init .
MESSAGE ID 'FES' TYPE 'E' NUMBER '024' RAISING unknown_error.
ENDTRY.
*----------------------------------------------------------------------*
*** Setup codepage converter
*----------------------------------------------------------------------*
DATA: converter TYPE REF TO cl_abap_conv_obj,
prc_codepage(4) TYPE n,
prc_miss TYPE c,
prc_broken TYPE c.
IF sy-subrc <> 0.
CASE sy-subrc.
WHEN 1.
MESSAGE ID 'FES' TYPE 'E' NUMBER '023' RAISING unknown_error.
WHEN 2.
MESSAGE ID 'FES' TYPE 'E' NUMBER '024' RAISING unknown_error.
ENDCASE.
ENDIF.
*----------------------------------------------------------------------*
*** Write header
*----------------------------------------------------------------------*
*----------------------------------------------------------------------*
*** BYTES: [0] : Version
*----------------------------------------------------------------------*
DATA: prc_version_number TYPE x VALUE 3.
CONCATENATE prc_output_string prc_version_number
INTO prc_output_string
IN BYTE MODE.
DATA: prc_day TYPE x,
prc_month TYPE x,
prc_year(2) TYPE x,
prc_year_short TYPE x.
*----------------------------------------------------------------------*
*** BYTES: [1] - [3]: Date of last change
*----------------------------------------------------------------------*
MOVE sy-datum(4) TO prc_year.
prc_year_short = prc_year - 1900.
MOVE sy-datum+4(2) TO prc_month.
MOVE sy-datum+6(2) TO prc_day.
CONCATENATE prc_output_string prc_year_short prc_month prc_day
INTO prc_output_string
IN BYTE MODE.
DATA: prc_enc_column_name TYPE xstring,
prc_enc_dbf_data_type TYPE xstring,
prc_enc_column_data TYPE xstring,
prc_enc_column_value TYPE xstring,
prc_enc_all_columns TYPE xstring,
prc_rec_len TYPE i VALUE 1,
prc_col_select TYPE c,
prc_col_mask_offset TYPE i,
prc_col_mask_length TYPE i. " Add 1 for additional SPACE
* Convert to little-endian
MOVE prc_lines_count TO prc_hex_lines_count.
MOVE prc_hex_lines_count(1) TO prc_hex_lines_count_le+3(1).
MOVE prc_hex_lines_count+1(1) TO prc_hex_lines_count_le+2(1).
MOVE prc_hex_lines_count+2(1) TO prc_hex_lines_count_le+1(1).
MOVE prc_hex_lines_count+3(1) TO prc_hex_lines_count_le(1).
CONCATENATE prc_output_string prc_hex_lines_count_le
prc_hex_header_len+1 prc_hex_header_len(1)
INTO prc_output_string
IN BYTE MODE.
*----------------------------------------------------------------------*
*** BYTES: [10] - [11]: record length
*----------------------------------------------------------------------*
DATA: prc_hex_rec_len(2) TYPE x.
MOVE prc_rec_len TO prc_hex_rec_len.
CONCATENATE prc_output_string prc_hex_rec_len+1 prc_hex_rec_len(1)
INTO prc_output_string
IN BYTE MODE.
*----------------------------------------------------------------------*
*** Column description
*----------------------------------------------------------------------*
CONCATENATE prc_output_string prc_enc_all_columns
INTO prc_output_string
IN BYTE MODE.
*----------------------------------------------------------------------*
*** End of Header
*----------------------------------------------------------------------*
DATA: prc_end_of_header TYPE x VALUE 13.
CONCATENATE prc_output_string prc_end_of_header INTO prc_output_string
IN BYTE MODE.
DATA: prc_val_tmp(40) TYPE c,
prc_enc_value_len TYPE i,
prc_spaces_to_add TYPE i,
prc_do_append TYPE c.
LOOP AT par_data_tab.
PERFORM addspaces USING 1
CHANGING prc_output_string.
prc_column_idx = 1.
WHILE prc_column_idx <= prc_all_columns_count.
"--- Select Columns for data ----------------------------------*
IF par_col_select IS INITIAL.
prc_col_select = 'X'.
ELSE.
prc_col_mask_offset = prc_column_idx - 1.
IF prc_col_mask_offset >= prc_col_mask_length.
CLEAR prc_col_select.
ELSE.
MOVE par_col_select_mask+prc_col_mask_offset(1)
TO prc_col_select.
ENDIF.
ENDIF.
CLEAR prc_column_name.
IF prc_col_select IS NOT INITIAL.
"--- End of Select Columns for Header -------------------------*
ASSIGN COMPONENT prc_column_idx OF STRUCTURE par_data_tab TO <f>.
DESCRIBE FIELD <f> TYPE prc_data_type
OUTPUT-LENGTH prc_output_length.
DESCRIBE FIELD <f> DECIMALS prc_dpts_length.
prc_do_append = 'X'.
IF prc_data_type = 'C' OR prc_data_type = 'D'.
DESCRIBE FIELD <f> LENGTH prc_output_length IN CHARACTER MODE.
ENDIF.
CASE prc_data_type.
WHEN 'C' OR 'D' OR 'T'.
prc_column_value = <f>.
WHEN 'X'.
prc_column_value = 'x'.
WRITE <f> TO prc_column_value+1.
CONDENSE prc_column_value NO-GAPS.
WHEN 'P' OR 'I' OR 'N' OR 'b' OR 's'.
CLEAR prc_val_tmp.
IF <f> < 0.
MOVE <f> TO prc_val_tmp+1.
TRANSLATE prc_val_tmp USING '- '.
WRITE '-' TO prc_val_tmp(1).
ELSE.
MOVE <f> TO prc_val_tmp.
ENDIF.
CONDENSE prc_val_tmp NO-GAPS.
* Write number right-aligned
DATA: prc_val_tmp_len TYPE i,
prc_shift_len TYPE i.
prc_val_tmp_len = STRLEN( prc_val_tmp ).
prc_shift_len = prc_output_length - prc_val_tmp_len.
IF prc_shift_len > 0.
SHIFT prc_val_tmp BY prc_shift_len PLACES RIGHT.
ENDIF.
prc_column_value = prc_val_tmp.
WHEN 'F'.
CLEAR prc_val_tmp.
IF <f> = 0.
prc_val_tmp = '0'.
ELSE.
WRITE <f> TO prc_val_tmp EXPONENT 0.
ENDIF.
TRANSLATE prc_val_tmp USING ',.'.
CONDENSE prc_val_tmp NO-GAPS.
prc_column_value = prc_val_tmp.
WHEN OTHERS. "// nothing, no append
CLEAR prc_do_append.
ENDCASE.
IF NOT prc_do_append IS INITIAL.
prc_column_value_str = prc_column_value.
CALL METHOD converter->convert
EXPORTING
inbuff = prc_column_value_str
inbufflg = 0
outbufflg = 0
IMPORTING
outbuff = prc_enc_column_value
EXCEPTIONS
internal_error = 1
OTHERS = 2.
IF sy-subrc <> 0.
CASE sy-subrc.
WHEN 1.
MESSAGE ID 'FES' TYPE 'E' NUMBER '024'
RAISING unknown_error.
WHEN 2.
MESSAGE ID 'FES' TYPE 'E' NUMBER '024'
RAISING unknown_error.
ENDCASE.
ENDIF.
CONCATENATE prc_output_string prc_enc_column_value INTO prc_output_string
IN BYTE MODE.
PERFORM addspaces USING prc_spaces_to_add
CHANGING prc_output_string.
ENDIF.
ENDIF.
prc_column_idx = prc_column_idx + 1.
ENDWHILE.
ENDLOOP.
*----------------------------------------------------------------------*
*** End of table marker
*----------------------------------------------------------------------*
DATA: prc_end_of_table TYPE x VALUE 26.
CONCATENATE prc_output_string prc_end_of_table INTO prc_output_string
IN BYTE MODE.
*----------------------------------------------------------------------*
*** Send data to dataprovider
*----------------------------------------------------------------------*
DATA: BEGIN OF hex_record,
myhex(1024) TYPE x,
END OF hex_record.
DATA: prc_hex_tab LIKE hex_record OCCURS 1 WITH HEADER LINE,
prc_bin_filesize TYPE i,
prc_rest TYPE i,
prc_dp_error TYPE i VALUE 0,
prc_dp_sysubrc TYPE i VALUE 0.
WHILE prc_rest > 1024.
prc_hex_tab-myhex = prc_output_string(1024).
APPEND prc_hex_tab.
MOVE prc_output_string+1024 TO prc_output_string.
prc_rest = prc_rest - 1024.
ENDWHILE.
IF prc_rest > 0.
prc_hex_tab-myhex = prc_output_string.
APPEND prc_hex_tab.
ENDIF.
**********************************************************************
DATA v_path TYPE text255.
v_path = par_filename.
DELETE DATASET v_path.
OPEN DATASET v_path FOR OUTPUT IN BINARY MODE.
LOOP AT prc_hex_tab.
TRANSFER prc_hex_tab TO v_path.
ENDLOOP.
CLOSE DATASET v_path.
*&---------------------------------------------------------------------*
*& Form BuildColumnInfo
*&---------------------------------------------------------------------*
FORM buildcolumninfo USING par_enc_column_name TYPE xstring
par_enc_dbf_data_type TYPE xstring
par_output_length TYPE i
par_dpts_length TYPE i
CHANGING par_column_data TYPE xstring.
DATA: prc_name_len TYPE i,
prc_bytes_to_add TYPE i,
prc_output_length TYPE x,
prc_dpts_length TYPE x.
PERFORM addzerobytes USING prc_bytes_to_add
CHANGING par_column_data.
CONCATENATE par_column_data par_enc_dbf_data_type INTO par_column_data
IN BYTE MODE.
prc_bytes_to_add = 4.
PERFORM addzerobytes USING prc_bytes_to_add
CHANGING par_column_data.
MOVE par_output_length TO prc_output_length.
MOVE par_dpts_length TO prc_dpts_length.
CONCATENATE par_column_data prc_output_length prc_dpts_length
INTO par_column_data
IN BYTE MODE.
prc_bytes_to_add = 14.
PERFORM addzerobytes USING prc_bytes_to_add
CHANGING par_column_data.
ENDFORM. " BuildColumnInfo
*&---------------------------------------------------------------------*
*& Form AddZeroBytes
*&---------------------------------------------------------------------*
FORM addzerobytes USING par_bytes_to_add TYPE i
CHANGING par_column_data.
DATA: i TYPE i,
x TYPE x.
i = 0.
CLEAR x.
WHILE i < par_bytes_to_add.
CONCATENATE par_column_data x INTO par_column_data IN BYTE MODE.
i = i + 1.
ENDWHILE.
ENDFORM. " AddZeroBytes
*&---------------------------------------------------------------------*
*& Form AddSpaces
*&---------------------------------------------------------------------*
FORM addspaces USING par_spaces_to_add TYPE i
CHANGING par_column_data.
DATA: i TYPE i,
x TYPE x VALUE 32.
i = 0.
WHILE i < par_spaces_to_add.
CONCATENATE par_column_data x INTO par_column_data IN BYTE MODE.
i = i + 1.
ENDWHILE.
ENDFORM. " AddSpaces
Код программы для тестирования
Code:
*
DATA BEGIN OF gs_file.
DATA field1 TYPE n LENGTH 10.
DATA field2 TYPE c LENGTH 20.
DATA END OF gs_file.
*
DATA BEGIN OF gs_fields.
DATA fieldname TYPE c LENGTH 15.
DATA END OF gs_fields.
*
DATA gt_file LIKE STANDARD TABLE OF gs_file.
*
DATA gt_fields LIKE STANDARD TABLE OF gs_fields.
INITIALIZATION.
PERFORM fill_data.
PERFORM fill_fields.
PERFORM download_dbf1
TABLES
gt_file
gt_fields
USING
'd:\test_dbf\test1.dbf'.
PERFORM download_dbf2
TABLES
gt_file
gt_fields
USING
'\\a01\test_dbf\test2.dbf'.
*&---------------------------------------------------------------------*
*& Form fill_data
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM fill_data.
DATA index TYPE string.
**********************************************************************`
DO 3 TIMES.
index = sy-index.
CLEAR gs_file.
gs_file-field1 = sy-index.
CONCATENATE 'Текст' index INTO gs_file-field2 SEPARATED BY space.
APPEND gs_file TO gt_file.
ENDDO.
ENDFORM. "fill_data
*&---------------------------------------------------------------------*
*& Form fill_fields
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM fill_fields.
CLEAR gt_fields.
CLEAR gs_fields.
gs_fields-fieldname = 'FIELD1'.
APPEND gs_fields TO gt_fields.
*&---------------------------------------------------------------------*
*& Form download_dbf
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->IT_DATA text
* -->IT_FIELDS text
* -->IV_FNAME text
*----------------------------------------------------------------------*
FORM download_dbf1 TABLES
it_data
it_fields
USING
iv_fname.
CALL FUNCTION 'GUI_DOWNLOAD'
EXPORTING
filename = iv_fname
filetype = 'DBF'
codepage = '1504 '
TABLES
data_tab = it_data
fieldnames = it_fields
EXCEPTIONS
file_write_error = 1
no_batch = 2
gui_refuse_filetransfer = 3
invalid_type = 4
no_authority = 5
unknown_error = 6
header_not_allowed = 7
separator_not_allowed = 8
filesize_not_allowed = 9
header_too_long = 10
dp_error_create = 11
dp_error_send = 12
dp_error_write = 13
unknown_dp_error = 14
access_denied = 15
dp_out_of_memory = 16
disk_full = 17
dp_timeout = 18
file_not_found = 19
dataprovider_exception = 20
control_flush_error = 21
OTHERS = 22.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ELSE.
MESSAGE s145(hrpadrureports) WITH iv_fname.
ENDIF.
ENDFORM. "download_dbf
*&---------------------------------------------------------------------*
*& Form download_dbf2
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->IT_DATA text
* -->IT_FIELDS text
* -->IV_FNAME text
*----------------------------------------------------------------------*
FORM download_dbf2 TABLES
it_data
it_fields
USING
iv_fname.
DATA: BEGIN OF hex_record,
myhex(1024) TYPE x,
END OF hex_record.
...
LOOP AT prc_hex_tab.
TRANSFER prc_hex_tab TO v_path.
ENDLOOP.
CLOSE DATASET v_path.
В последней строчке prc_hex_tab у вас скажем 300 байт вашей информации, и 724 байта забито нулями. А выгружается строчка целиком
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.