├── .abapgit.xml
├── LICENSE
├── README.md
├── abaplint.json
├── docs
└── img
│ └── cover.png
└── src
├── package.devc.xml
├── zcl_tbox_csv_common.clas.abap
├── zcl_tbox_csv_common.clas.locals_imp.abap
├── zcl_tbox_csv_common.clas.xml
├── zcl_tbox_csv_reader.clas.abap
├── zcl_tbox_csv_reader.clas.locals_imp.abap
├── zcl_tbox_csv_reader.clas.xml
├── zcl_tbox_csv_writer.clas.abap
├── zcl_tbox_csv_writer.clas.xml
├── zcl_tbox_csvfield.clas.abap
├── zcl_tbox_csvfield.clas.xml
├── zcl_tbox_csvman.clas.abap
├── zcl_tbox_csvman.clas.xml
├── zcl_tbox_csvman_apack.clas.abap
├── zcl_tbox_csvman_apack.clas.xml
├── zcx_tbox_csvman.clas.abap
└── zcx_tbox_csvman.clas.xml
/.abapgit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | E
6 | /src/
7 | PREFIX
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Marco Marrone
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ABAP CSV Manager
2 |
3 | 
4 |
5 | ## Requirement
6 | :cloud: ABAP for Cloud Development edition
7 |
8 | Looking for *On-Premise* edition? Switch to *onprem-main* branch.
9 |
10 | ## Quick Start
11 |
12 | :office_worker: **I need to read a CSV, how can I do it?**
13 |
14 | :mage: Create a *reader* instance and call `read` method.
15 | ```abap
16 | DATA(csv_reader) = zcl_tbox_csvman=>get_reader( ).
17 | csv_reader->read(
18 | EXPORTING i_csv = csv_data
19 | IMPORTING e_table = tab_data ).
20 | ```
21 |
22 | :office_worker: **I need to create a CSV, how can I do it?**
23 |
24 | :mage: Create a *writer* instance and call `write` method.
25 | ```abap
26 | DATA(csv_writer) = zcl_tbox_csvman=>get_writer( ).
27 | DATA(csv_data) = csv_reader->write( tab_data ).
28 |
29 | * csv_data is a string, if you need the output as a string table:
30 | DATA(csv_data) = csv_reader->write_to_string_table( tab_data ).
31 | ```
32 |
33 | ### Some remarks about reading a CSV
34 |
35 | When you call the `read` method of a *reader* instance,
36 | `csv_data` can be:
37 | - a string
38 | - a table of strings
39 | - a table with one-component table line
40 |
41 | `tab_data` must be a *flat* table: a table whose table line is a structure, whose components are simple elements.
42 |
43 | Sometimes you need to read a CSV but you don't know a priori how many and which columns it contains. In these cases you still have two ways to read it:
44 |
45 | - you can get a reference variable to a table whose fields (of type string) are named F1, F2, ..., FN and so on;
46 | ```abap
47 | DATA(csv_ref) = csv_reader->read_with_reference( csv_data ).
48 |
49 | FIELD-SYMBOLS TYPE STANDARD TABLE.
50 | ASSIGN csv_ref->* TO .
51 |
52 | LOOP AT ASSIGNING FIELD-SYMBOL().
53 | DATA(row_index) = sy-tabix.
54 | DO.
55 | ASSIGN COMPONENT sy-index OF STRUCTURE TO FIELD-SYMBOL().
56 | IF sy-subrc <> 0.
57 | EXIT.
58 | ENDIF.
59 | DATA(info) = |The value at row { row_index } and column { sy-index } is { }| ).
60 | ENDDO.
61 | ENDLOOP.
62 |
63 | * You can always get a statically typed table using dereference method
64 | csv_reader->dereference( EXPORTING i_reference = csv_ref IMPORTING e_table = safe_data ).
65 | ```
66 |
67 | - or you can get a transposed version of the CSV, that is, a table with two fields: the row index and a table containing the list of its values, for each column.
68 |
69 | ```abap
70 | DATA(csv_tab_t) = csv_reader->read_with_transposition( csv_data ).
71 |
72 | LOOP AT csv_tab_t INTO DATA(csv_row).
73 | LOOP AT csv_row-row INTO DATA(row_values).
74 |
75 | DATA(info) = |The value at row { csv_row-row_index } and column { row_values-column_index } is { row_values-value }| ).
76 |
77 | ENDLOOP.
78 | ENDLOOP.
79 |
80 | * You can always get a standard table, if you have a suitable variable, using detranspose method
81 | csv_reader->detranspose( EXPORTING i_transposed = csv_tab_t IMPORTING e_table = safe_data ).
82 | ```
83 |
84 | ## General Configuration
85 | :office_worker: **Can I decide which character to use as delimiter, quotechar, and line terminator? And what about escaping special characters?**
86 |
87 | :mage: Once instantiated you can configure the csv management object:
88 | - ``csv_man->delimiter( `;` ).`` *fields delimiter, default is semicolon:* `;`*. Here "delimiter" is a synonym of "separator".*
89 | - ``csv_man->quotechar( `"` ).`` *to quote fields, default is none.
90 | - ``csv_man->end_of_line( `|` ).`` *line-terminator char, default is Carriage Return and Line Feed* `%_CR_LF` *.*
91 | - ``csv_man->escapechar( `/` ).`` *to escape special characters, both in read and write mode.*
92 | - ``csv_man->doublequote( ).`` *to escape a quotechar character with a quotechar character.*
93 | - `csv_man->quoting( ztbox_cl_csvman=>c_quote_minimal ).` *to restrict quoting application, with these options:*
94 | - `zcl_tbox_csv_writer=>c_quote_all` *to apply quotechar character to all fields (this is default behaviour if a quotechar is set);*
95 | - `zcl_tbox_csv_writer=>c_quote_minimal` *to apply quotechar character only to fields containing special characters;*
96 | - `zcl_tbox_csv_writer=>c_quote_nonnumeric` *to apply quotechar character only to non-numeric fields;*
97 | - `zcl_tbox_csv_writer=>c_quote_none` *to never quote fields (this is the default behaviour if no quotechar is set).*
98 | - `csv_man->header( ).` *to write/expect an header line in write/read mode. Default is* `abap_true` *.*
99 | - `csv_man->header_desc( ).` *to use field name as header text field. You can column text by calling* `->label( )` *method on fields level, see below for details.*
100 |
101 | ## Output Format
102 | :office_worker: **Nice, but I want also control fields output format, especially for date/time/numeric fields.**
103 |
104 | :mage: Sure, you can use these configurations:
105 | - ``csv_man->date_format( `yyyy/dd/mm` ).`` *to decide output format for date fields in write mode, or to declare expected format for date fields in read mode. You can use any format containing "dd", "mm", "yy", "yyyy" and an optional separator. Default is* `dd.mm.yyyy`.
106 | - ``csv_man->time_format( `hh:mm:ss` ).`` *same as above, but for time fields. Default is* `hh:mm:ss`.
107 | - `csv_man->number_format( ).` *three options here:*
108 | - ` ` *(blank) to output numbers like* `1.234.567,89`
109 | - `X` *to output numbers like* `1,234,567.89`
110 | - `Y` *to output numbers like* `1 234 567,89`
111 | - ``csv_man->country( `US` ).`` *to output date, time and numbers according to a country rules (less specific than previous methods).*
112 | - `csv_man->decimals( 3 ).` *to write numerical fields with the specified decimals precision.*
113 | - `csv_man->condense_values( ).` *to remove leading and trailing spaces. Default is* `abap_false`.
114 | - `csv_man->keep_init( ).` *to maintain initial values: if set to* `abap_false` *a numerical field containing only 0, as well as an initial date or initial time, became blank in write mode. Default is* `abap_true`.
115 | - `csv_man->alignment( cl_abap_format=>a_right ).` *to align fields content according to the following options:*
116 | - `cl_abap_format=>a_left` *to justify text on the left (default option);*
117 | - `cl_abap_format=>a_right` *to justify text on the right.*
118 |
119 | ## Fields Properties
120 | :office_worker: **Ok cool. These are global configuration, valid for all the fields, aren't they? What if I want to set some format property to one field and a different property to another?**
121 |
122 | :mage: You can restrict the application of the previous methods to a single field by calling `field( )` method first, also chaining other methods, e.g.:
123 |
124 | ```abap
125 | csv_man->field( `AMOUNT_USD` )->number_format( `X` ).
126 | csv_man->field( `AMOUNT_EUR` )->country( `IT` )->decimals( 2 ).
127 | ```
128 | You can also exclude some fields from the CSV generation/reading process using `exclude( )` method:
129 |
130 | ```abap
131 | csv_man->field( `MANDT` )->exclude( ).
132 | ```
133 |
134 | Viceversa, if you work with a table having too many fields, you can generate or reading a CSV considering only a small subset of fields using `include( )` method. Once you have called `include` for a field, only fields for which `include` has been called will be considered.
135 |
136 | ```abap
137 | csv_man->field( `MATNR` )->include( ).
138 | csv_man->field( `WERKS` )->include( ).
139 | ```
140 |
141 | If the order of the fields in the table does not match the columns in the CSV to generate or read, you can map each field with the corresponding csv-column position:
142 |
143 | ```abap
144 | csv_man->header_desc( abap_true ).
145 | csv_man->field( `MATNR` )->position( 2 )->label( `Material!!!` ).
146 | csv_man->field( `WERKS` )->position( 1 )->label( `THE Plant` ).
147 | ```
148 | In this way, the following table:
149 | | MATNR | WERKS |
150 | | ------- | ------ |
151 | | AAAA01 | US01 |
152 | | BBBB02 | US02 |
153 |
154 | gives this CSV as output:
155 | ```csv
156 | THE Plant,Material!!!
157 | US01,AAAA01
158 | US02,BBBB02
159 | ```
160 |
161 | `label( )` method set a custom header text when `header_desc( )` is used.
162 |
163 | ## Validations
164 | :office_worker: **Regarding reading the csv, is there an automatism to help identify errors in the data?**
165 |
166 | :mage: We have it. When a CSV is read, some validation checks are performed according to the data type of the target fields: date fields (if not blank) must be a valid and plausible date; time fields (if not blank) must contain a valid and plausible time, numerical fields (if not blank) must contain a valid number. Whenever any of these check fail, the contents are not transferred. You get a detailed report for the validation fails by calling `get_validations_fails( )`.
167 |
168 | Suppose you read this CSV:
169 |
170 | ```csv
171 | 31/02/2023,10:45:19,"1900,20"
172 | 28/02/2023,25:00:00,"-894,23"
173 | 31/12/2022,00:00:01,"12A4,43"
174 | ```
175 |
176 | into a table with structure `DATE [D(8)] | TIME [T(6)] | AMOUNT [P(7) DEC(2)]`. The output will be
177 | | DATE | TIME | AMOUNT |
178 | | ------- | ------ | ------ |
179 | | 00000000 | 104519 | 1900.20 |
180 | | 20230228 | 000000 | -894.00 |
181 | | 20221231 | 000001 | 0.00 |
182 |
183 | And the `get_validation_fails( )` output is this table:
184 | | ROW | COL | TABLE_FIELD | CSV_VALUE | SAP_VALUE | CHECK_FAILED |
185 | | ------- | ------- | ------- | ------- | ------- | ------- |
186 | | 1 | 1 | DATE | 31/02/2023 | 20230231 | DATE_PLAUSIBILITY |
187 | | 2 | 2 | TIME | 25:00:00 | 250000 | TIME_PLAUSIBILITY |
188 | | 3 | 3 | AMOUNT | 12A4,43 | 12A4.43 | VALID_NUMB |
189 |
190 | You can add also custom validation checks: it must be an instance method with the following signature
191 |
192 | ```abap
193 | METHODS sample_check IMPORTING i_value TYPE string RETURNING VALUE(r_fail) TYPE flag.
194 | ```
195 | If, e.g., an object `sample_object` implements method `sample_check`, you can add this check to a field:
196 |
197 | ```abap
198 | csv_man->field( `FIELD_NAME` )->add_post_validation(
199 | check_object = sample_object
200 | check_method = `SAMPLE_CHECK` ).
201 | ```
202 |
203 | in two ways: as a *pre validation* by calling method `add_pre_validation( )`, and as a *post validation* by calling method `add_post_validation( )`.
204 | - Pre-validation checks are applied to raw data: parameter `value` is a string containing exactly the content of the field in the CSV;
205 | - Post-validation checks are applied to transformed data: parameter `value` is a string containing the field value interally formatted for the SAP data type field target, according to the format options configured.
206 |
207 | `fail = abap_true` means the check has not been passed.
208 |
209 | ## Installation
210 | Install this project using [abapGit](https://abapgit.org/) 
211 |
--------------------------------------------------------------------------------
/abaplint.json:
--------------------------------------------------------------------------------
1 | {
2 | "global": {
3 | "files": "/src/**/*.*",
4 | "skipGeneratedGatewayClasses": true,
5 | "skipGeneratedPersistentClasses": true,
6 | "skipGeneratedFunctionGroups": true
7 | },
8 | "syntax": {
9 | "version": "v753",
10 | "errorNamespace": "",
11 | "globalConstants": [],
12 | "globalMacros": []
13 | },
14 | "dependencies": [
15 | {
16 | "url": "https://github.com/abaplint/deps",
17 | "folder": "/deps",
18 | "files": "/src/**/*.*"
19 | }
20 | ],
21 | "rules": {
22 | "avoid_use": {
23 | "define": true,
24 | "endselect": true,
25 | "execSQL": true,
26 | "kernelCall": true,
27 | "communication": true,
28 | "statics": true,
29 | "systemCall": true,
30 | "break": true,
31 | "defaultKey": true
32 | },
33 | "commented_code": true,
34 | "constructor_visibility_public": true,
35 | "description_empty": false,
36 | "empty_statement": true,
37 | "empty_structure": {
38 | "loop": true,
39 | "if": true,
40 | "while": true,
41 | "case": true,
42 | "select": true,
43 | "do": true,
44 | "at": true,
45 | "try": true
46 | },
47 | "exporting": true,
48 | "functional_writing": {
49 | "ignoreExceptions": true
50 | },
51 | "global_class": true,
52 | "identical_form_names": true,
53 | "if_in_if": true,
54 | "inline_data_old_versions": true,
55 | "line_length": {
56 | "length": 120
57 | },
58 | "max_one_statement": true,
59 | "message_exists": true,
60 | "method_length": {
61 | "statements": 25,
62 | "ignoreTestClasses": false,
63 | "errorWhenEmpty": true
64 | },
65 | "mix_returning": true,
66 | "msag_consistency": true,
67 | "nesting": {
68 | "depth": 5
69 | },
70 | "obsolete_statement": {
71 | "refresh": true,
72 | "compute": true,
73 | "add": true,
74 | "subtract": true,
75 | "multiply": true,
76 | "move": true,
77 | "divide": true,
78 | "requested": true,
79 | "occurs": true,
80 | "setExtended": true,
81 | "withHeaderLine": true,
82 | "fieldSymbolStructure": true
83 | },
84 | "parser_error": true,
85 | "preferred_compare_operator": {
86 | "badOperators": [
87 | "EQ",
88 | "NE",
89 | "GE",
90 | "GT",
91 | "LT",
92 | "LE"
93 | ]
94 | },
95 | "short_case": {
96 | "length": 1,
97 | "allow": []
98 | },
99 | "superclass_final": true,
100 | "unreachable_code": true,
101 | "use_new": true,
102 | "when_others_last": true,
103 | "ambiguous_statement": true,
104 | "begin_end_names": true,
105 | "check_transformation_exists": true,
106 | "check_syntax": false,
107 | "form_tables_obsolete": true,
108 | "tabl_enhancement_category": true,
109 | "implement_methods": true,
110 | "local_testclass_location": true,
111 | "main_file_contents": true,
112 | "rfc_error_handling": true,
113 | "indentation": {
114 | "alignTryCatch": false,
115 | "ignoreExceptions": false,
116 | "globalClassSkipFirst": false,
117 | "ignoreGlobalClassDefinition": false,
118 | "ignoreGlobalInterface": false
119 | },
120 | "sequential_blank": {
121 | "lines": 3
122 | },
123 | "empty_line_in_statement": {
124 | "allowChained": true
125 | },
126 | "check_abstract": true,
127 | "no_public_attributes": {
128 | "allowReadOnly": true
129 | },
130 | "abapdoc": false,
131 | "prefer_returning_to_exporting": true,
132 | "keep_single_parameter_on_one_line": {
133 | "length": 120
134 | },
135 | "allowed_object_naming": true,
136 | "fully_type_constants": true,
137 | "check_comments": {
138 | "allowEndOfLine": true
139 | },
140 | "check_text_elements": true,
141 | "newline_between_methods": {
142 | "logic": "less",
143 | "count": 3
144 | },
145 | "check_include": true,
146 | "xml_consistency": true,
147 | "prefix_is_current_class": {
148 | "omitMeInstanceCalls": true
149 | },
150 | "check_no_handler_pragma": true,
151 | "line_break_multiple_parameters": true,
152 | "prefer_inline": true,
153 | "reduce_string_templates": true,
154 | "sicf_consistency": true,
155 | "sql_escape_host_variables": true,
156 | "try_without_catch": true,
157 | "names_no_dash": true,
158 | "unknown_types": false,
159 | "unused_variables": true,
160 | "unused_types": true,
161 | "use_bool_expression": true,
162 | "use_line_exists": true,
163 | "check_subrc": true,
164 | "cyclomatic_complexity": {
165 | "max": 6
166 | },
167 | "parser_missing_space": true,
168 | "identical_conditions": true,
169 | "prefer_is_not": true
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/docs/img/cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zenrosadira/abap-tbox-csvman/9f1d8b8fd6b6cacb335dece8020cf5e824eb3614/docs/img/cover.png
--------------------------------------------------------------------------------
/src/package.devc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | TBOX | CSV Manager
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/zcl_tbox_csv_common.clas.abap:
--------------------------------------------------------------------------------
1 | CLASS zcl_tbox_csv_common DEFINITION
2 | PUBLIC
3 | CREATE PROTECTED
4 | GLOBAL FRIENDS zcl_tbox_csvfield.
5 |
6 | PUBLIC SECTION.
7 | METHODS field
8 | IMPORTING i_name TYPE clike
9 | RETURNING VALUE(r_res) TYPE REF TO zcl_tbox_csvfield.
10 |
11 | METHODS header_desc
12 | IMPORTING i_active TYPE abap_bool DEFAULT abap_true
13 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csv_common.
14 |
15 | METHODS header
16 | IMPORTING i_active TYPE abap_bool DEFAULT abap_true
17 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csv_common.
18 |
19 | METHODS doublequote
20 | IMPORTING i_active TYPE abap_bool DEFAULT abap_true
21 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csv_common.
22 |
23 | METHODS quoting
24 | IMPORTING i_quoting TYPE i
25 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csv_common.
26 |
27 | METHODS escapechar
28 | IMPORTING i_escapechar TYPE clike
29 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csv_common.
30 |
31 | METHODS quotechar
32 | IMPORTING i_quotechar TYPE clike
33 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csv_common.
34 |
35 | METHODS delimiter
36 | IMPORTING i_delimiter TYPE clike
37 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csv_common.
38 |
39 | METHODS end_of_line
40 | IMPORTING i_eof TYPE clike
41 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csv_common.
42 |
43 | METHODS decimals
44 | IMPORTING i_decimals TYPE i
45 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csv_common.
46 |
47 | METHODS number_format
48 | IMPORTING i_number_format TYPE clike
49 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csv_common.
50 |
51 | METHODS time_format
52 | IMPORTING i_time_format TYPE clike
53 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csv_common.
54 |
55 | METHODS date_format
56 | IMPORTING i_date_format TYPE clike
57 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csv_common.
58 |
59 | METHODS country
60 | IMPORTING i_country TYPE land1
61 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csv_common.
62 |
63 | METHODS keep_init
64 | IMPORTING i_active TYPE abap_bool DEFAULT abap_true
65 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csv_common.
66 |
67 | METHODS alignment
68 | IMPORTING i_alignment TYPE i
69 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csv_common.
70 |
71 | METHODS condense_values
72 | IMPORTING i_active TYPE abap_bool DEFAULT abap_true
73 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csv_common.
74 |
75 | PROTECTED SECTION.
76 | TYPES:
77 | BEGIN OF ts_date_format,
78 | dd_off TYPE i,
79 | mm_off TYPE i,
80 | yy_off TYPE i,
81 | yy_len TYPE i,
82 | sep TYPE c LENGTH 1,
83 | END OF ts_date_format.
84 | TYPES:
85 | BEGIN OF ts_time_format,
86 | hh_off TYPE i,
87 | mm_off TYPE i,
88 | ss_off TYPE i,
89 | sep TYPE c LENGTH 1,
90 | END OF ts_time_format.
91 | TYPES:
92 | BEGIN OF ts_general_params,
93 | header TYPE abap_bool,
94 | header_desc TYPE abap_bool,
95 | end_of_line TYPE string,
96 | quotechar TYPE c LENGTH 1,
97 | delimiter TYPE c LENGTH 1,
98 | escapechar TYPE c LENGTH 1,
99 | doublequote TYPE abap_bool,
100 | quoting TYPE i,
101 | END OF ts_general_params.
102 | TYPES:
103 | BEGIN OF ts_format_params,
104 | convexit TYPE abap_bool,
105 | condense TYPE abap_bool,
106 | alignment TYPE i,
107 | keep_init TYPE abap_bool,
108 | country TYPE land1,
109 | date_format TYPE ts_date_format,
110 | time_format TYPE ts_time_format,
111 | number_format TYPE c LENGTH 1,
112 | decimals TYPE i,
113 | use_number_format TYPE abap_bool,
114 | END OF ts_format_params.
115 | TYPES:
116 | BEGIN OF ts_catalog,
117 | field TYPE c LENGTH 30,
118 | field_obj TYPE REF TO zcl_tbox_csvfield,
119 | END OF ts_catalog.
120 | TYPES:
121 | BEGIN OF ts_fields_map,
122 | field TYPE c LENGTH 30,
123 | position TYPE i,
124 | END OF ts_fields_map.
125 |
126 | DATA m_catalog TYPE TABLE OF ts_catalog WITH KEY field.
127 | DATA m_include_fields TYPE RANGE OF string.
128 | DATA m_exclude_fields TYPE RANGE OF string.
129 | DATA m_fields_mapping TYPE TABLE OF ts_fields_map WITH KEY field.
130 | DATA m_general_params TYPE ts_general_params.
131 | DATA m_format_params TYPE ts_format_params.
132 | DATA m_decimals_set TYPE abap_bool.
133 |
134 | METHODS _set_catalog
135 | IMPORTING i_table TYPE ANY TABLE
136 | RAISING zcx_tbox_csvman.
137 |
138 | PRIVATE SECTION.
139 | METHODS _next_free_catalog_position
140 | RETURNING VALUE(r) TYPE i.
141 |
142 | CLASS-METHODS _create_time_format
143 | IMPORTING i_time_format TYPE clike
144 | RETURNING VALUE(r_time_format) TYPE ts_time_format.
145 |
146 | CLASS-METHODS _create_date_format
147 | IMPORTING i_date_format TYPE clike
148 | RETURNING VALUE(r_date_format) TYPE ts_date_format.
149 | ENDCLASS.
150 |
151 |
152 | CLASS zcl_tbox_csv_common IMPLEMENTATION.
153 | * ---------------------------------------------------------------------------------------+
154 | * | Instance Public Method ZCL_TBOX_CSV_COMMON->ALIGNMENT
155 | * +-------------------------------------------------------------------------------------------------+
156 | * | [--->] I_ALIGNMENT TYPE I
157 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSV_COMMON
158 | * +--------------------------------------------------------------------------------------
159 | METHOD alignment.
160 | m_format_params-alignment = i_alignment.
161 |
162 | r = me.
163 | ENDMETHOD.
164 |
165 | * ---------------------------------------------------------------------------------------+
166 | * | Instance Public Method ZCL_TBOX_CSV_COMMON->CONDENSE_VALUES
167 | * +-------------------------------------------------------------------------------------------------+
168 | * | [--->] I_ACTIVE TYPE ABAP_BOOL (default =ABAP_TRUE)
169 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSV_COMMON
170 | * +--------------------------------------------------------------------------------------
171 | METHOD condense_values.
172 | m_format_params-condense = i_active.
173 |
174 | r = me.
175 | ENDMETHOD.
176 |
177 | * ---------------------------------------------------------------------------------------+
178 | * | Instance Public Method ZCL_TBOX_CSV_COMMON->COUNTRY
179 | * +-------------------------------------------------------------------------------------------------+
180 | * | [--->] I_COUNTRY TYPE LAND1
181 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSV_COMMON
182 | * +--------------------------------------------------------------------------------------
183 | METHOD country.
184 | m_format_params-country = i_country.
185 |
186 | r = me.
187 | ENDMETHOD.
188 |
189 | * ---------------------------------------------------------------------------------------+
190 | * | Instance Public Method ZCL_TBOX_CSV_COMMON->DATE_FORMAT
191 | * +-------------------------------------------------------------------------------------------------+
192 | * | [--->] I_DATE_FORMAT TYPE CLIKE
193 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSV_COMMON
194 | * +--------------------------------------------------------------------------------------
195 | METHOD date_format.
196 | m_format_params-date_format = _create_date_format( i_date_format ).
197 |
198 | r = me.
199 | ENDMETHOD.
200 |
201 | * ---------------------------------------------------------------------------------------+
202 | * | Instance Public Method ZCL_TBOX_CSV_COMMON->DECIMALS
203 | * +-------------------------------------------------------------------------------------------------+
204 | * | [--->] I_DECIMALS TYPE I
205 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSV_COMMON
206 | * +--------------------------------------------------------------------------------------
207 | METHOD decimals.
208 | m_format_params-decimals = i_decimals.
209 | m_decimals_set = abap_true.
210 |
211 | r = me.
212 | ENDMETHOD.
213 |
214 | * ---------------------------------------------------------------------------------------+
215 | * | Instance Public Method ZCL_TBOX_CSV_COMMON->DELIMITER
216 | * +-------------------------------------------------------------------------------------------------+
217 | * | [--->] I_DELIMITER TYPE CLIKE
218 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSV_COMMON
219 | * +--------------------------------------------------------------------------------------
220 | METHOD delimiter.
221 | m_general_params-delimiter = i_delimiter.
222 |
223 | r = me.
224 | ENDMETHOD.
225 |
226 | * ---------------------------------------------------------------------------------------+
227 | * | Instance Public Method ZCL_TBOX_CSV_COMMON->DOUBLEQUOTE
228 | * +-------------------------------------------------------------------------------------------------+
229 | * | [--->] I_ACTIVE TYPE ABAP_BOOL (default =ABAP_TRUE)
230 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSV_COMMON
231 | * +--------------------------------------------------------------------------------------
232 | METHOD doublequote.
233 | m_general_params-doublequote = i_active.
234 |
235 | r = me.
236 | ENDMETHOD.
237 |
238 | * ---------------------------------------------------------------------------------------+
239 | * | Instance Public Method ZCL_TBOX_CSV_COMMON->END_OF_LINE
240 | * +-------------------------------------------------------------------------------------------------+
241 | * | [--->] I_EOF TYPE CLIKE
242 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSV_COMMON
243 | * +--------------------------------------------------------------------------------------
244 | METHOD end_of_line.
245 | m_general_params-end_of_line = i_eof.
246 |
247 | r = me.
248 | ENDMETHOD.
249 |
250 | * ---------------------------------------------------------------------------------------+
251 | * | Instance Public Method ZCL_TBOX_CSV_COMMON->ESCAPECHAR
252 | * +-------------------------------------------------------------------------------------------------+
253 | * | [--->] I_ESCAPECHAR TYPE CLIKE
254 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSV_COMMON
255 | * +--------------------------------------------------------------------------------------
256 | METHOD escapechar.
257 | m_general_params-escapechar = i_escapechar.
258 |
259 | r = me.
260 | ENDMETHOD.
261 |
262 | * ---------------------------------------------------------------------------------------+
263 | * | Instance Public Method ZCL_TBOX_CSV_COMMON->FIELD
264 | * +-------------------------------------------------------------------------------------------------+
265 | * | [--->] I_NAME TYPE CLIKE
266 | * | [<-()] R_RES TYPE REF TO ZCL_TBOX_CSVFIELD
267 | * +--------------------------------------------------------------------------------------
268 | METHOD field.
269 | IF NOT line_exists( m_catalog[ field = i_name ] ).
270 |
271 | INSERT VALUE #( field = i_name
272 | field_obj = NEW #( i_name = i_name
273 | i_csv = me ) ) INTO TABLE m_catalog.
274 |
275 | ENDIF.
276 |
277 | r_res = m_catalog[ field = i_name ]-field_obj.
278 | ENDMETHOD.
279 |
280 | * ---------------------------------------------------------------------------------------+
281 | * | Instance Public Method ZCL_TBOX_CSV_COMMON->HEADER
282 | * +-------------------------------------------------------------------------------------------------+
283 | * | [--->] I_ACTIVE TYPE ABAP_BOOL (default =ABAP_TRUE)
284 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSV_COMMON
285 | * +--------------------------------------------------------------------------------------
286 | METHOD header.
287 | m_general_params-header = i_active.
288 |
289 | r = me.
290 | ENDMETHOD.
291 |
292 | * ---------------------------------------------------------------------------------------+
293 | * | Instance Public Method ZCL_TBOX_CSV_COMMON->HEADER_DESC
294 | * +-------------------------------------------------------------------------------------------------+
295 | * | [--->] I_ACTIVE TYPE ABAP_BOOL (default =ABAP_TRUE)
296 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSV_COMMON
297 | * +--------------------------------------------------------------------------------------
298 | METHOD header_desc.
299 | m_general_params-header_desc = i_active.
300 |
301 | r = me.
302 | ENDMETHOD.
303 |
304 | * ---------------------------------------------------------------------------------------+
305 | * | Instance Public Method ZCL_TBOX_CSV_COMMON->KEEP_INIT
306 | * +-------------------------------------------------------------------------------------------------+
307 | * | [--->] I_ACTIVE TYPE ABAP_BOOL (default =ABAP_TRUE)
308 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSV_COMMON
309 | * +--------------------------------------------------------------------------------------
310 | METHOD keep_init.
311 | m_format_params-keep_init = i_active.
312 |
313 | r = me.
314 | ENDMETHOD.
315 |
316 | * ---------------------------------------------------------------------------------------+
317 | * | Instance Public Method ZCL_TBOX_CSV_COMMON->NUMBER_FORMAT
318 | * +-------------------------------------------------------------------------------------------------+
319 | * | [--->] I_NUMBER_FORMAT TYPE CLIKE
320 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSV_COMMON
321 | * +--------------------------------------------------------------------------------------
322 | METHOD number_format.
323 | m_format_params-number_format = i_number_format.
324 | m_format_params-use_number_format = abap_true.
325 |
326 | r = me.
327 | ENDMETHOD.
328 |
329 | * ---------------------------------------------------------------------------------------+
330 | * | Instance Public Method ZCL_TBOX_CSV_COMMON->QUOTECHAR
331 | * +-------------------------------------------------------------------------------------------------+
332 | * | [--->] I_QUOTECHAR TYPE CLIKE
333 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSV_COMMON
334 | * +--------------------------------------------------------------------------------------
335 | METHOD quotechar.
336 | m_general_params-quotechar = i_quotechar.
337 |
338 | r = me.
339 | ENDMETHOD.
340 |
341 | * ---------------------------------------------------------------------------------------+
342 | * | Instance Public Method ZCL_TBOX_CSV_COMMON->QUOTING
343 | * +-------------------------------------------------------------------------------------------------+
344 | * | [--->] I_QUOTING TYPE I
345 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSV_COMMON
346 | * +--------------------------------------------------------------------------------------
347 | METHOD quoting.
348 | m_general_params-quoting = i_quoting.
349 |
350 | r = me.
351 | ENDMETHOD.
352 |
353 | * ---------------------------------------------------------------------------------------+
354 | * | Instance Public Method ZCL_TBOX_CSV_COMMON->TIME_FORMAT
355 | * +-------------------------------------------------------------------------------------------------+
356 | * | [--->] I_TIME_FORMAT TYPE CLIKE
357 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSV_COMMON
358 | * +--------------------------------------------------------------------------------------
359 | METHOD time_format.
360 | m_format_params-time_format = _create_time_format( i_time_format ).
361 |
362 | r = me.
363 | ENDMETHOD.
364 |
365 | * ---------------------------------------------------------------------------------------+
366 | * | Static Private Method ZCL_TBOX_CSV_COMMON=>_CREATE_DATE_FORMAT
367 | * +-------------------------------------------------------------------------------------------------+
368 | * | [--->] I_DATE_FORMAT TYPE CLIKE
369 | * | [<-()] R_DATE_FORMAT TYPE TS_DATE_FORMAT
370 | * +--------------------------------------------------------------------------------------
371 | METHOD _create_date_format.
372 | DATA(d2_off) = find( val = i_date_format
373 | sub = `dd`
374 | case = abap_false ).
375 | DATA(m2_off) = find( val = i_date_format
376 | sub = `mm`
377 | case = abap_false ).
378 | DATA(y2_off) = find( val = i_date_format
379 | sub = `yy`
380 | case = abap_false ).
381 | DATA(y4_off) = find( val = i_date_format
382 | sub = `yyyy`
383 | case = abap_false ).
384 | DATA(y4_cnt) = count( val = i_date_format
385 | sub = `yyyy`
386 | case = abap_false ).
387 |
388 | DATA(sep_off) = nmin( val1 = d2_off
389 | val2 = m2_off ) + 2.
390 |
391 | r_date_format = VALUE #( sep = i_date_format+sep_off(1)
392 | dd_off = d2_off
393 | mm_off = m2_off
394 | yy_off = COND #( WHEN y4_cnt > 0 THEN y4_off ELSE y2_off )
395 | yy_len = COND #( WHEN y4_cnt > 0 THEN 4 ELSE 2 ) ).
396 | ENDMETHOD.
397 |
398 | * ---------------------------------------------------------------------------------------+
399 | * | Static Private Method ZCL_TBOX_CSV_COMMON=>_CREATE_TIME_FORMAT
400 | * +-------------------------------------------------------------------------------------------------+
401 | * | [--->] I_TIME_FORMAT TYPE CLIKE
402 | * | [<-()] R_TIME_FORMAT TYPE TS_TIME_FORMAT
403 | * +--------------------------------------------------------------------------------------
404 | METHOD _create_time_format.
405 | DATA(h2_off) = find( val = i_time_format
406 | sub = `hh`
407 | case = abap_false ).
408 | DATA(m2_off) = find( val = i_time_format
409 | sub = `mm`
410 | case = abap_false ).
411 | DATA(s2_off) = find( val = i_time_format
412 | sub = `ss`
413 | case = abap_false ).
414 |
415 | DATA(p_off) = nmin( val1 = s2_off
416 | val2 = m2_off ) + 2.
417 |
418 | r_time_format = VALUE #( sep = i_time_format+p_off(1)
419 | hh_off = h2_off
420 | mm_off = m2_off
421 | ss_off = s2_off ).
422 | ENDMETHOD.
423 |
424 | * ---------------------------------------------------------------------------------------+
425 | * | Instance Private Method ZCL_TBOX_CSV_COMMON->_NEXT_FREE_CATALOG_POSITION
426 | * +-------------------------------------------------------------------------------------------------+
427 | * | [<-()] R TYPE I
428 | * +--------------------------------------------------------------------------------------
429 | METHOD _next_free_catalog_position.
430 | DO lines( m_catalog ) TIMES.
431 |
432 | IF NOT line_exists( m_fields_mapping[ position = sy-index ] ).
433 | r = sy-index.
434 | EXIT.
435 | ENDIF.
436 |
437 | ENDDO.
438 | ENDMETHOD.
439 |
440 | * ---------------------------------------------------------------------------------------+
441 | * | Instance Protected Method ZCL_TBOX_CSV_COMMON->_SET_CATALOG
442 | * +-------------------------------------------------------------------------------------------------+
443 | * | [--->] I_TABLE TYPE ANY TABLE
444 | * | [!CX!] ZCX_TBOX_CSVMAN
445 | * +--------------------------------------------------------------------------------------
446 | METHOD _set_catalog.
447 | IF NOT lcl_utils=>is_flat_table( i_table ).
448 | RAISE EXCEPTION NEW zcx_tbox_csvman( text = `Invalid table.` ).
449 | ENDIF.
450 |
451 | DATA(components) = lcl_utils=>get_components( i_table ).
452 |
453 | LOOP AT components INTO DATA(component).
454 |
455 | IF m_include_fields IS NOT INITIAL AND component-name NOT IN m_include_fields.
456 | DELETE m_catalog WHERE field = component-name.
457 | DELETE m_fields_mapping WHERE field = component-name.
458 | CONTINUE.
459 | ENDIF.
460 |
461 | IF m_exclude_fields IS NOT INITIAL.
462 | IF component-name IN m_exclude_fields.
463 | CONTINUE.
464 | ENDIF.
465 | ENDIF.
466 |
467 | field( component-name )->_assign_element( CAST cl_abap_elemdescr( component-type ) ).
468 |
469 | IF NOT line_exists( m_fields_mapping[ field = component-name ] ).
470 | INSERT VALUE #( field = component-name
471 | position = _next_free_catalog_position( ) ) INTO TABLE m_fields_mapping.
472 | ENDIF.
473 |
474 | ENDLOOP.
475 |
476 | SORT m_fields_mapping BY position.
477 | ENDMETHOD.
478 | ENDCLASS.
479 |
--------------------------------------------------------------------------------
/src/zcl_tbox_csv_common.clas.locals_imp.abap:
--------------------------------------------------------------------------------
1 | CLASS lcl_utils DEFINITION.
2 | PUBLIC SECTION.
3 | CLASS-METHODS get_components IMPORTING i_data TYPE data
4 | RETURNING VALUE(r) TYPE abap_component_view_tab.
5 |
6 | CLASS-METHODS is_flat_table IMPORTING i_table TYPE ANY TABLE
7 | RETURNING VALUE(r) TYPE abap_bool.
8 |
9 | ENDCLASS.
10 |
11 |
12 | CLASS lcl_utils IMPLEMENTATION.
13 | METHOD get_components.
14 | DATA(data_desc) = cl_abap_typedescr=>describe_by_data( i_data ).
15 |
16 | CASE data_desc->kind.
17 |
18 | WHEN cl_abap_typedescr=>kind_table.
19 |
20 | DATA(tab_desc) = CAST cl_abap_tabledescr( data_desc ).
21 | DATA(tab_line) = tab_desc->get_table_line_type( ).
22 |
23 | CASE tab_line->kind.
24 |
25 | WHEN cl_abap_typedescr=>kind_struct.
26 | DATA(line_desc) = CAST cl_abap_structdescr( tab_line ).
27 | r = line_desc->get_included_view( ).
28 |
29 | WHEN OTHERS.
30 | r = VALUE #( ( name = |TABLE_LINE|
31 | type = tab_line ) ).
32 |
33 | ENDCASE.
34 |
35 | WHEN cl_abap_typedescr=>kind_struct.
36 |
37 | DATA(struct_desc) = CAST cl_abap_structdescr( data_desc ).
38 | r = struct_desc->get_included_view( ).
39 |
40 | ENDCASE.
41 | ENDMETHOD.
42 |
43 | METHOD is_flat_table.
44 | DATA(data_desc) = cl_abap_typedescr=>describe_by_data( i_table ).
45 | IF data_desc->kind <> cl_abap_typedescr=>kind_table.
46 | RETURN.
47 | ENDIF.
48 |
49 | DATA(tab_desc) = CAST cl_abap_tabledescr( data_desc ).
50 | DATA(tab_line) = tab_desc->get_table_line_type( ).
51 | IF tab_line->kind <> cl_abap_typedescr=>kind_struct.
52 | RETURN.
53 | ENDIF.
54 |
55 | DATA(struct_line) = CAST cl_abap_structdescr( tab_line ).
56 | DATA(components) = struct_line->get_included_view( ).
57 |
58 | LOOP AT components INTO DATA(component).
59 |
60 | IF component-type->kind <> cl_abap_typedescr=>kind_elem.
61 | RETURN.
62 | ENDIF.
63 |
64 | ENDLOOP.
65 |
66 | r = abap_true.
67 | ENDMETHOD.
68 | ENDCLASS.
69 |
--------------------------------------------------------------------------------
/src/zcl_tbox_csv_common.clas.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ZCL_TBOX_CSV_COMMON
7 | E
8 | CSV Manager | Common Methods
9 | 1
10 | X
11 | X
12 | X
13 |
14 |
15 | -
16 | I
17 | E01
18 | Invalid table: table line must contain only simple elements
19 | 100
20 |
21 |
22 |
23 |
24 | FIELD
25 | R_RES
26 | E
27 | CSV Manager | CSV Field
28 |
29 |
30 | _SET_CATALOG
31 | ZCX_TBOX_CSVMAN
32 | E
33 | CSV Manager Exceptions
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/zcl_tbox_csv_reader.clas.abap:
--------------------------------------------------------------------------------
1 | CLASS zcl_tbox_csv_reader DEFINITION
2 | PUBLIC
3 | INHERITING FROM zcl_tbox_csv_common
4 | FINAL
5 | CREATE PRIVATE
6 | GLOBAL FRIENDS zcl_tbox_csvfield
7 | zcl_tbox_csvman.
8 |
9 | PUBLIC SECTION.
10 | TYPES:
11 | BEGIN OF ts_validation_fails,
12 | row TYPE i,
13 | col TYPE i,
14 | table_field TYPE c LENGTH 30,
15 | csv_value TYPE string,
16 | sap_value TYPE string,
17 | check_failed TYPE c LENGTH 30,
18 | END OF ts_validation_fails.
19 | TYPES tt_validation_fails TYPE TABLE OF ts_validation_fails WITH EMPTY KEY.
20 | TYPES:
21 | BEGIN OF ts_transposed_row,
22 | column_index TYPE i,
23 | value TYPE string,
24 | END OF ts_transposed_row.
25 | TYPES:
26 | BEGIN OF ts_transposed_tab,
27 | row_index TYPE i,
28 | row TYPE TABLE OF ts_transposed_row WITH KEY column_index,
29 | END OF ts_transposed_tab.
30 | TYPES tt_transposed_tab TYPE TABLE OF ts_transposed_tab WITH KEY row_index.
31 |
32 | METHODS read
33 | IMPORTING i_csv TYPE data
34 | EXPORTING e_table TYPE ANY TABLE
35 | RAISING zcx_tbox_csvman.
36 |
37 | METHODS get_validation_fails
38 | RETURNING VALUE(r) TYPE tt_validation_fails.
39 |
40 | METHODS constructor.
41 |
42 | METHODS dereference
43 | IMPORTING i_reference TYPE REF TO data
44 | EXPORTING e_table TYPE ANY TABLE
45 | RAISING zcx_tbox_csvman.
46 |
47 | METHODS detranspose
48 | IMPORTING i_transposed TYPE tt_transposed_tab
49 | EXPORTING e_table TYPE ANY TABLE
50 | RAISING zcx_tbox_csvman.
51 |
52 | METHODS read_with_transposition
53 | IMPORTING i_csv TYPE data
54 | RETURNING VALUE(r) TYPE tt_transposed_tab
55 | RAISING zcx_tbox_csvman.
56 |
57 | METHODS read_with_reference
58 | IMPORTING i_csv TYPE data
59 | RETURNING VALUE(r) TYPE REF TO data
60 | RAISING zcx_tbox_csvman.
61 |
62 | PROTECTED SECTION.
63 |
64 | PRIVATE SECTION.
65 | DATA _csv_string_table TYPE string_table.
66 | DATA _table_of_strings TYPE REF TO data.
67 | DATA m_validation_fails TYPE tt_validation_fails.
68 | DATA m_current_row TYPE i.
69 | DATA m_current_col TYPE i.
70 | DATA m_current_field TYPE string.
71 | DATA m_current_value TYPE string.
72 | DATA m_current_line TYPE string.
73 |
74 | METHODS _set_csv_string_table
75 | IMPORTING csv TYPE data.
76 |
77 | METHODS _parse_csv
78 | EXPORTING e_table TYPE ANY TABLE
79 | RAISING zcx_tbox_csvman.
80 |
81 | METHODS _parse_line
82 | IMPORTING !line TYPE string
83 | RETURNING VALUE(r) TYPE string_table.
84 |
85 | METHODS _parse_fields
86 | IMPORTING !values TYPE string_table
87 | RETURNING VALUE(r) TYPE string_table.
88 |
89 | METHODS _add_validation_fail
90 | IMPORTING i_check_failed TYPE clike
91 | i_sap_value TYPE string OPTIONAL.
92 |
93 | METHODS _default_config.
94 |
95 | CLASS-METHODS _new_guid
96 | RETURNING VALUE(result) TYPE sysuuid_c22.
97 |
98 | METHODS _identify_special_character
99 | IMPORTING i_special_characeter TYPE string
100 | RETURNING VALUE(r) TYPE sysuuid_c22.
101 |
102 | METHODS _transpose_csv
103 | RETURNING VALUE(r) TYPE tt_transposed_tab.
104 | ENDCLASS.
105 |
106 |
107 | CLASS zcl_tbox_csv_reader IMPLEMENTATION.
108 | * ---------------------------------------------------------------------------------------+
109 | * | Instance Public Method ZCL_TBOX_CSV_READER->CONSTRUCTOR
110 | * +-------------------------------------------------------------------------------------------------+
111 | * +--------------------------------------------------------------------------------------
112 | METHOD constructor.
113 | super->constructor( ).
114 |
115 | _default_config( ).
116 | ENDMETHOD.
117 |
118 | * ---------------------------------------------------------------------------------------+
119 | * | Instance Public Method ZCL_TBOX_CSV_READER->DEREFERENCE
120 | * +-------------------------------------------------------------------------------------------------+
121 | * | [--->] I_REFERENCE TYPE REF TO DATA
122 | * | [<---] E_TABLE TYPE ANY TABLE
123 | * | [!CX!] ZCX_TBOX_CSVMAN
124 | * +--------------------------------------------------------------------------------------
125 | METHOD dereference.
126 | CHECK i_reference IS BOUND.
127 | ASSIGN i_reference->* TO FIELD-SYMBOL().
128 | IF sy-subrc <> 0.
129 | RETURN.
130 | ENDIF.
131 |
132 | DATA(csv_tab) = zcl_tbox_csvman=>get_writer( )->write_to_string_table( ).
133 |
134 | read( EXPORTING i_csv = csv_tab IMPORTING e_table = e_table ).
135 | ENDMETHOD.
136 |
137 | * ---------------------------------------------------------------------------------------+
138 | * | Instance Public Method ZCL_TBOX_CSV_READER->DETRANSPOSE
139 | * +-------------------------------------------------------------------------------------------------+
140 | * | [--->] I_TRANSPOSED TYPE TT_TRANSPOSED_TAB
141 | * | [<---] E_TABLE TYPE ANY TABLE
142 | * | [!CX!] ZCX_TBOX_CSVMAN
143 | * +--------------------------------------------------------------------------------------
144 | METHOD detranspose.
145 | DATA row_ref TYPE REF TO data.
146 |
147 | _set_catalog( e_table ).
148 |
149 | LOOP AT i_transposed INTO DATA(csv_line).
150 |
151 | m_current_row = sy-tabix.
152 |
153 | DATA(values) = csv_line-row.
154 |
155 | CREATE DATA row_ref LIKE LINE OF e_table.
156 | ASSIGN row_ref->* TO FIELD-SYMBOL().
157 | IF sy-subrc <> 0.
158 | CONTINUE.
159 | ENDIF.
160 |
161 | LOOP AT m_fields_mapping INTO DATA(map).
162 |
163 | CLEAR m_current_value.
164 | READ TABLE values INTO DATA(csv_row) INDEX map-position.
165 | IF sy-subrc <> 0.
166 | CONTINUE.
167 | ENDIF.
168 |
169 | m_current_value = csv_row-value.
170 | m_current_col = map-position.
171 | m_current_field = map-field.
172 |
173 | DATA(field_obj) = VALUE #( m_catalog[ field = m_current_field ]-field_obj OPTIONAL ).
174 | IF field_obj IS NOT BOUND.
175 | CONTINUE.
176 | ENDIF.
177 |
178 | ASSIGN COMPONENT m_current_field OF STRUCTURE TO FIELD-SYMBOL().
179 | IF sy-subrc <> 0.
180 | CONTINUE.
181 | ENDIF.
182 | = field_obj->_read( m_current_value ).
183 |
184 | ENDLOOP.
185 |
186 | INSERT INTO TABLE e_table.
187 |
188 | ENDLOOP.
189 | ENDMETHOD.
190 |
191 | * ---------------------------------------------------------------------------------------+
192 | * | Instance Public Method ZCL_TBOX_CSV_READER->GET_VALIDATION_FAILS
193 | * +-------------------------------------------------------------------------------------------------+
194 | * | [<-()] R TYPE TT_VALIDATION_FAILS
195 | * +--------------------------------------------------------------------------------------
196 | METHOD get_validation_fails.
197 | r = m_validation_fails.
198 | ENDMETHOD.
199 |
200 | * ---------------------------------------------------------------------------------------+
201 | * | Instance Public Method ZCL_TBOX_CSV_READER->READ
202 | * +-------------------------------------------------------------------------------------------------+
203 | * | [--->] I_CSV TYPE DATA
204 | * | [<---] E_TABLE TYPE ANY TABLE
205 | * | [!CX!] ZCX_TBOX_CSVMAN
206 | * +--------------------------------------------------------------------------------------
207 | METHOD read.
208 | _set_catalog( e_table ).
209 |
210 | _set_csv_string_table( i_csv ).
211 |
212 | _parse_csv( IMPORTING e_table = e_table ).
213 | ENDMETHOD.
214 |
215 | * ---------------------------------------------------------------------------------------+
216 | * | Instance Public Method ZCL_TBOX_CSV_READER->READ_WITH_REFERENCE
217 | * +-------------------------------------------------------------------------------------------------+
218 | * | [--->] I_CSV TYPE DATA
219 | * | [<-()] R TYPE REF TO DATA
220 | * | [!CX!] ZCX_TBOX_CSVMAN
221 | * +--------------------------------------------------------------------------------------
222 | METHOD read_with_reference.
223 | CLEAR: m_catalog,
224 | m_fields_mapping.
225 |
226 | FIELD-SYMBOLS TYPE ANY TABLE.
227 |
228 | _set_csv_string_table( i_csv ).
229 |
230 | IF _csv_string_table IS INITIAL.
231 | RETURN.
232 | ENDIF.
233 |
234 | DATA(first_line) = _parse_line( _csv_string_table[ 1 ] ).
235 |
236 | DATA(tab_of_strings) = lcl_utils=>create_type_table_from_catalog(
237 | VALUE #( FOR _col IN first_line INDEX INTO i
238 | ( name = |F{ i }|
239 | type = CAST cl_abap_elemdescr( cl_abap_typedescr=>describe_by_data( VALUE string( ) ) ) ) ) ).
240 |
241 | ASSIGN tab_of_strings->* TO .
242 | IF sy-subrc <> 0.
243 | RETURN.
244 | ENDIF.
245 |
246 | _set_catalog( ).
247 |
248 | _parse_csv( IMPORTING e_table = ).
249 |
250 | r = tab_of_strings.
251 |
252 | CLEAR: m_catalog,
253 | m_fields_mapping.
254 | ENDMETHOD.
255 |
256 | * ---------------------------------------------------------------------------------------+
257 | * | Instance Public Method ZCL_TBOX_CSV_READER->READ_WITH_TRANSPOSITION
258 | * +-------------------------------------------------------------------------------------------------+
259 | * | [--->] I_CSV TYPE DATA
260 | * | [<-()] R TYPE TT_TRANSPOSED_TAB
261 | * | [!CX!] ZCX_TBOX_CSVMAN
262 | * +--------------------------------------------------------------------------------------
263 | METHOD read_with_transposition.
264 | CLEAR: m_catalog,
265 | m_fields_mapping.
266 |
267 | _set_csv_string_table( i_csv ).
268 |
269 | r = _transpose_csv( ).
270 | ENDMETHOD.
271 |
272 | * ---------------------------------------------------------------------------------------+
273 | * | Instance Private Method ZCL_TBOX_CSV_READER->_ADD_VALIDATION_FAIL
274 | * +-------------------------------------------------------------------------------------------------+
275 | * | [--->] I_CHECK_FAILED TYPE CLIKE
276 | * | [--->] I_SAP_VALUE TYPE STRING(optional)
277 | * +--------------------------------------------------------------------------------------
278 | METHOD _add_validation_fail.
279 | INSERT VALUE #( row = m_current_row
280 | col = m_current_col
281 | table_field = m_current_field
282 | csv_value = m_current_value
283 | sap_value = i_sap_value
284 | check_failed = i_check_failed ) INTO TABLE m_validation_fails.
285 | ENDMETHOD.
286 |
287 | * ---------------------------------------------------------------------------------------+
288 | * | Instance Private Method ZCL_TBOX_CSV_READER->_DEFAULT_CONFIG
289 | * +-------------------------------------------------------------------------------------------------+
290 | * +--------------------------------------------------------------------------------------
291 | METHOD _default_config.
292 | header( ).
293 | delimiter( `;` ).
294 | end_of_line( cl_abap_char_utilities=>cr_lf ).
295 | date_format( `dd.mm.yyyy` ).
296 | time_format( `hh:mm:ss` ).
297 | ENDMETHOD.
298 |
299 | * ---------------------------------------------------------------------------------------+
300 | * | Instance Private Method ZCL_TBOX_CSV_READER->_IDENTIFY_SPECIAL_CHARACTER
301 | * +-------------------------------------------------------------------------------------------------+
302 | * | [--->] I_SPECIAL_CHARACETER TYPE STRING
303 | * | [<-()] R TYPE SYSUUID_C22
304 | * +--------------------------------------------------------------------------------------
305 | METHOD _identify_special_character.
306 | CHECK m_general_params-escapechar IS NOT INITIAL.
307 | CHECK count( val = m_current_line
308 | sub = i_special_characeter ) <> 0.
309 |
310 | r = _new_guid( ).
311 |
312 | m_current_line = replace( val = m_current_line
313 | occ = 0
314 | sub = i_special_characeter
315 | with = r ).
316 | ENDMETHOD.
317 |
318 | * ---------------------------------------------------------------------------------------+
319 | * | Static Private Method ZCL_TBOX_CSV_READER=>_NEW_GUID
320 | * +-------------------------------------------------------------------------------------------------+
321 | * | [<-()] RESULT TYPE SYSUUID_C22
322 | * +--------------------------------------------------------------------------------------
323 | METHOD _new_guid.
324 | TRY.
325 | result = cl_system_uuid=>create_uuid_c22_static( ).
326 | CATCH cx_uuid_error.
327 | RETURN.
328 | ENDTRY.
329 | ENDMETHOD.
330 |
331 | * ---------------------------------------------------------------------------------------+
332 | * | Instance Private Method ZCL_TBOX_CSV_READER->_PARSE_CSV
333 | * +-------------------------------------------------------------------------------------------------+
334 | * | [<---] E_TABLE TYPE ANY TABLE
335 | * | [!CX!] ZCX_TBOX_CSVMAN
336 | * +--------------------------------------------------------------------------------------
337 | METHOD _parse_csv.
338 | DATA row_ref TYPE REF TO data.
339 |
340 | IF m_general_params-header = abap_true.
341 | DELETE _csv_string_table INDEX 1.
342 | ENDIF.
343 |
344 | LOOP AT _csv_string_table INTO DATA(csv_line).
345 |
346 | m_current_row = sy-tabix.
347 |
348 | DATA(values) = _parse_line( csv_line ).
349 |
350 | CREATE DATA row_ref LIKE LINE OF e_table.
351 | ASSIGN row_ref->* TO FIELD-SYMBOL().
352 | IF sy-subrc <> 0.
353 | CONTINUE.
354 | ENDIF.
355 |
356 | LOOP AT m_fields_mapping INTO DATA(map).
357 |
358 | CLEAR m_current_value.
359 | READ TABLE values INTO m_current_value INDEX map-position.
360 | IF sy-subrc <> 0.
361 | CONTINUE.
362 | ENDIF.
363 |
364 | m_current_col = map-position.
365 | m_current_field = map-field.
366 |
367 | DATA(field_obj) = VALUE #( m_catalog[ field = m_current_field ]-field_obj OPTIONAL ).
368 | IF field_obj IS NOT BOUND.
369 | CONTINUE.
370 | ENDIF.
371 |
372 | ASSIGN COMPONENT m_current_field OF STRUCTURE TO FIELD-SYMBOL().
373 | IF sy-subrc <> 0.
374 | CONTINUE.
375 | ENDIF.
376 | = field_obj->_read( m_current_value ).
377 |
378 | ENDLOOP.
379 |
380 | INSERT INTO TABLE e_table.
381 |
382 | ENDLOOP.
383 | ENDMETHOD.
384 |
385 | * ---------------------------------------------------------------------------------------+
386 | * | Instance Private Method ZCL_TBOX_CSV_READER->_PARSE_FIELDS
387 | * +-------------------------------------------------------------------------------------------------+
388 | * | [--->] VALUES TYPE STRING_TABLE
389 | * | [<-()] R TYPE STRING_TABLE
390 | * +--------------------------------------------------------------------------------------
391 | METHOD _parse_fields.
392 | IF lines( values ) = 1.
393 | r = values.
394 | RETURN.
395 | ENDIF.
396 |
397 | DATA(tot_enc) = 0.
398 | DATA(combine) = abap_false.
399 | DATA(val_combined) = VALUE string( ).
400 |
401 | LOOP AT values INTO DATA(value).
402 |
403 | IF m_general_params-escapechar IS NOT INITIAL.
404 | DATA(c_esc) = count( val = value
405 | off = 0
406 | sub = |{ m_general_params-escapechar }{ m_general_params-quotechar }| ).
407 | ENDIF.
408 |
409 | IF m_general_params-quotechar IS NOT INITIAL.
410 | DATA(c_enc) = count( val = value
411 | off = 0
412 | sub = m_general_params-quotechar ).
413 | ENDIF.
414 |
415 | tot_enc += c_enc - c_esc.
416 |
417 | CASE tot_enc MOD 2.
418 |
419 | WHEN 0.
420 |
421 | IF combine = abap_true.
422 | val_combined = val_combined && m_general_params-delimiter && value.
423 | value = val_combined.
424 | ENDIF.
425 |
426 | IF value IS NOT INITIAL AND m_general_params-quotechar IS NOT INITIAL.
427 |
428 | DATA(condensed_value) = condense( value ).
429 | IF condensed_value IS NOT INITIAL.
430 | DATA(val_first) = condensed_value(1).
431 | DATA(val_last) = substring( val = condensed_value
432 | off = strlen( condensed_value ) - 1
433 | len = 1 ).
434 |
435 | IF val_last = m_general_params-quotechar AND val_first = m_general_params-quotechar.
436 | value = substring( val = condensed_value
437 | off = 1
438 | len = strlen( condensed_value ) - 2 ).
439 | ENDIF.
440 | ENDIF.
441 |
442 | ENDIF.
443 |
444 | IF m_general_params-escapechar IS NOT INITIAL.
445 | value = replace( val = value
446 | occ = 0
447 | sub = m_general_params-escapechar && m_general_params-quotechar
448 | with = m_general_params-quotechar ).
449 | ENDIF.
450 |
451 | APPEND value TO r.
452 | CLEAR: value,
453 | val_combined,
454 | combine.
455 |
456 | WHEN OTHERS.
457 |
458 | combine = abap_true.
459 | val_combined = COND #(
460 | WHEN val_combined IS INITIAL
461 | THEN value
462 | ELSE val_combined && m_general_params-delimiter && value ).
463 |
464 | ENDCASE.
465 |
466 | ENDLOOP.
467 | ENDMETHOD.
468 |
469 | * ---------------------------------------------------------------------------------------+
470 | * | Instance Private Method ZCL_TBOX_CSV_READER->_PARSE_LINE
471 | * +-------------------------------------------------------------------------------------------------+
472 | * | [--->] LINE TYPE STRING
473 | * | [<-()] R TYPE STRING_TABLE
474 | * +--------------------------------------------------------------------------------------
475 | METHOD _parse_line.
476 | m_current_line = line.
477 |
478 | DATA(guid_esc) = _identify_special_character( m_general_params-escapechar && m_general_params-escapechar ).
479 | DATA(guid_del) = _identify_special_character( m_general_params-escapechar && m_general_params-delimiter ).
480 |
481 | SPLIT m_current_line AT m_general_params-delimiter INTO TABLE DATA(values).
482 |
483 | DATA(nextolast) = strlen( m_current_line ) - 1.
484 | IF m_current_line+nextolast(1) = m_general_params-delimiter.
485 | APPEND VALUE string( ) TO values.
486 | ENDIF.
487 |
488 | r = _parse_fields( values ).
489 |
490 | IF guid_del IS NOT INITIAL.
491 | REPLACE ALL OCCURRENCES OF guid_del IN TABLE r WITH m_general_params-delimiter.
492 | ENDIF.
493 |
494 | IF guid_esc IS NOT INITIAL.
495 | REPLACE ALL OCCURRENCES OF guid_del IN TABLE r WITH m_general_params-escapechar.
496 | ENDIF.
497 | ENDMETHOD.
498 |
499 | * ---------------------------------------------------------------------------------------+
500 | * | Instance Private Method ZCL_TBOX_CSV_READER->_SET_CSV_STRING_TABLE
501 | * +-------------------------------------------------------------------------------------------------+
502 | * | [--->] CSV TYPE DATA
503 | * +--------------------------------------------------------------------------------------
504 | METHOD _set_csv_string_table.
505 | CASE abap_true.
506 |
507 | WHEN lcl_utils=>is_elem( csv ).
508 | SPLIT csv AT m_general_params-end_of_line INTO TABLE _csv_string_table.
509 |
510 | WHEN lcl_utils=>is_table_of_elem( csv ).
511 | MOVE-CORRESPONDING csv TO _csv_string_table.
512 |
513 | WHEN lcl_utils=>is_table_of_one_component( csv ).
514 | FIELD-SYMBOLS TYPE ANY TABLE.
515 | ASSIGN csv TO .
516 | IF sy-subrc <> 0.
517 | RETURN.
518 | ENDIF.
519 |
520 | LOOP AT ASSIGNING FIELD-SYMBOL().
521 |
522 | ASSIGN COMPONENT 1 OF STRUCTURE TO FIELD-SYMBOL().
523 | IF sy-subrc <> 0.
524 | CONTINUE.
525 | ENDIF.
526 | APPEND TO _csv_string_table.
527 |
528 | ENDLOOP.
529 |
530 | ENDCASE.
531 | ENDMETHOD.
532 |
533 | * ---------------------------------------------------------------------------------------+
534 | * | Instance Private Method ZCL_TBOX_CSV_READER->_TRANSPOSE_CSV
535 | * +-------------------------------------------------------------------------------------------------+
536 | * | [<-()] R TYPE TT_TRANSPOSED_TAB
537 | * +--------------------------------------------------------------------------------------
538 | METHOD _transpose_csv.
539 | IF m_general_params-header = abap_true.
540 | DELETE _csv_string_table INDEX 1.
541 | ENDIF.
542 |
543 | r = VALUE #( FOR _line IN _csv_string_table INDEX INTO i
544 | LET _values = _parse_line( _line ) IN
545 | ( row_index = i
546 | row = VALUE #( FOR _val IN _values INDEX INTO j
547 | ( column_index = j
548 | value = _val ) ) ) ).
549 | ENDMETHOD.
550 | ENDCLASS.
551 |
--------------------------------------------------------------------------------
/src/zcl_tbox_csv_reader.clas.locals_imp.abap:
--------------------------------------------------------------------------------
1 | CLASS lcl_utils DEFINITION.
2 | PUBLIC SECTION.
3 | CLASS-METHODS is_elem
4 | IMPORTING i_data TYPE data
5 | RETURNING VALUE(r) TYPE abap_bool.
6 |
7 | CLASS-METHODS is_table_of_elem
8 | IMPORTING i_data TYPE data
9 | RETURNING VALUE(r) TYPE abap_bool.
10 |
11 | CLASS-METHODS is_table_of_one_component
12 | IMPORTING i_data TYPE data
13 | RETURNING VALUE(r) TYPE abap_bool.
14 |
15 | CLASS-METHODS create_type_table_from_catalog
16 | IMPORTING i_catalog TYPE abap_component_view_tab
17 | RETURNING VALUE(r) TYPE REF TO data.
18 |
19 | ENDCLASS.
20 |
21 |
22 | CLASS lcl_utils IMPLEMENTATION.
23 | METHOD is_elem.
24 | r = xsdbool( cl_abap_typedescr=>describe_by_data( i_data )->kind = cl_abap_typedescr=>kind_elem ).
25 | ENDMETHOD.
26 |
27 | METHOD is_table_of_elem.
28 | DATA(data_desc) = cl_abap_typedescr=>describe_by_data( i_data ).
29 | IF data_desc->kind <> cl_abap_typedescr=>kind_table.
30 | RETURN.
31 | ENDIF.
32 |
33 | DATA(tab_desc) = CAST cl_abap_tabledescr( data_desc ).
34 | IF tab_desc->get_table_line_type( )->kind <> cl_abap_typedescr=>kind_elem.
35 | RETURN.
36 | ENDIF.
37 |
38 | r = abap_true.
39 | ENDMETHOD.
40 |
41 | METHOD is_table_of_one_component.
42 | DATA(data_desc) = cl_abap_typedescr=>describe_by_data( i_data ).
43 | IF data_desc->kind <> cl_abap_typedescr=>kind_table.
44 | RETURN.
45 | ENDIF.
46 |
47 | DATA(tab_desc) = CAST cl_abap_tabledescr( data_desc ).
48 | DATA(tab_line) = tab_desc->get_table_line_type( ).
49 | IF tab_line->kind <> cl_abap_typedescr=>kind_struct.
50 | RETURN.
51 | ENDIF.
52 |
53 | DATA(struct_line) = CAST cl_abap_structdescr( tab_line ).
54 | DATA(components) = struct_line->get_included_view( ).
55 |
56 | r = xsdbool( lines( components ) = 1 AND components[ 1 ]-type->kind = cl_abap_typedescr=>kind_elem ).
57 | ENDMETHOD.
58 |
59 | METHOD create_type_table_from_catalog.
60 | DATA(line_type) = cl_abap_structdescr=>get( CORRESPONDING #( i_catalog ) ).
61 |
62 | DATA(tab_type) = cl_abap_tabledescr=>get( p_line_type = line_type
63 | p_key_kind = cl_abap_tabledescr=>keydefkind_empty ).
64 |
65 | CREATE DATA r TYPE HANDLE tab_type.
66 | ENDMETHOD.
67 | ENDCLASS.
68 |
--------------------------------------------------------------------------------
/src/zcl_tbox_csv_reader.clas.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ZCL_TBOX_CSV_READER
7 | E
8 | CSV Reader
9 | 1
10 | X
11 | X
12 | X
13 |
14 |
15 |
16 | _CSV_STRING_TABLE
17 | E
18 | Table of Strings
19 |
20 |
21 |
22 |
23 | DEREFERENCE
24 | ZCX_TBOX_CSVMAN
25 | E
26 | CSV Manager Exceptions
27 |
28 |
29 | DETRANSPOSE
30 | ZCX_TBOX_CSVMAN
31 | E
32 | CSV Manager Exceptions
33 |
34 |
35 | READ
36 | ZCX_TBOX_CSVMAN
37 | E
38 | CSV Manager Exceptions
39 |
40 |
41 | READ_WITH_REFERENCE
42 | ZCX_TBOX_CSVMAN
43 | E
44 | CSV Manager Exceptions
45 |
46 |
47 | READ_WITH_TRANSPOSITION
48 | ZCX_TBOX_CSVMAN
49 | E
50 | CSV Manager Exceptions
51 |
52 |
53 | _IDENTIFY_SPECIAL_CHARACTER
54 | R
55 | E
56 | 16 Byte UUID in 22 Characters (Usually Base64 Encoded)
57 |
58 |
59 | _NEW_GUID
60 | RESULT
61 | E
62 | 16 Byte UUID in 22 Characters (Usually Base64 Encoded)
63 |
64 |
65 | _PARSE_CSV
66 | ZCX_TBOX_CSVMAN
67 | E
68 | CSV Manager Exceptions
69 |
70 |
71 | _PARSE_FIELDS
72 | R
73 | E
74 | Table of Strings
75 |
76 |
77 | _PARSE_FIELDS
78 | VALUES
79 | E
80 | Table of Strings
81 |
82 |
83 | _PARSE_LINE
84 | LINE
85 | E
86 | Table of Strings
87 |
88 |
89 | _PARSE_LINE
90 | R
91 | E
92 | Table of Strings
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/src/zcl_tbox_csv_writer.clas.abap:
--------------------------------------------------------------------------------
1 | CLASS zcl_tbox_csv_writer DEFINITION
2 | PUBLIC
3 | INHERITING FROM zcl_tbox_csv_common
4 | FINAL
5 | CREATE PRIVATE
6 | GLOBAL FRIENDS zcl_tbox_csvman.
7 |
8 | PUBLIC SECTION.
9 | CONSTANTS c_quote_all TYPE i VALUE 3.
10 | CONSTANTS c_quote_minimal TYPE i VALUE 1.
11 | CONSTANTS c_quote_nonnumeric TYPE i VALUE 2.
12 | CONSTANTS c_quote_none TYPE i VALUE 0.
13 |
14 | METHODS constructor.
15 |
16 | METHODS write
17 | IMPORTING i_table TYPE ANY TABLE
18 | RETURNING VALUE(r_csv) TYPE string
19 | RAISING zcx_tbox_csvman.
20 |
21 | METHODS _create_csv
22 | IMPORTING i_table TYPE ANY TABLE
23 | RETURNING VALUE(r_csv) TYPE string.
24 |
25 | METHODS write_to_string_table
26 | IMPORTING i_table TYPE ANY TABLE
27 | RETURNING VALUE(r) TYPE string_table
28 | RAISING zcx_tbox_csvman.
29 |
30 | PROTECTED SECTION.
31 |
32 | PRIVATE SECTION.
33 | DATA m_current_field_obj TYPE REF TO zcl_tbox_csvfield.
34 |
35 | METHODS _apply_escapings
36 | CHANGING c_value TYPE string.
37 |
38 | METHODS _apply_quotings
39 | CHANGING c_value TYPE string.
40 |
41 | METHODS _get_header
42 | RETURNING VALUE(r) TYPE string.
43 |
44 | METHODS _default_config.
45 |
46 | METHODS _to_string_table
47 | IMPORTING i_csv_string TYPE string
48 | RETURNING VALUE(r) TYPE string_table.
49 | ENDCLASS.
50 |
51 |
52 | CLASS zcl_tbox_csv_writer IMPLEMENTATION.
53 | * ---------------------------------------------------------------------------------------+
54 | * | Instance Public Method ZCL_TBOX_CSV_WRITER->CONSTRUCTOR
55 | * +-------------------------------------------------------------------------------------------------+
56 | * +--------------------------------------------------------------------------------------
57 | METHOD constructor.
58 | super->constructor( ).
59 |
60 | _default_config( ).
61 | ENDMETHOD.
62 |
63 | * ---------------------------------------------------------------------------------------+
64 | * | Instance Public Method ZCL_TBOX_CSV_WRITER->WRITE
65 | * +-------------------------------------------------------------------------------------------------+
66 | * | [--->] I_TABLE TYPE ANY TABLE
67 | * | [<-()] R_CSV TYPE STRING
68 | * | [!CX!] ZCX_TBOX_CSVMAN
69 | * +--------------------------------------------------------------------------------------
70 | METHOD write.
71 | _set_catalog( i_table ).
72 |
73 | r_csv = _create_csv( i_table ).
74 | ENDMETHOD.
75 |
76 | * ---------------------------------------------------------------------------------------+
77 | * | Instance Public Method ZCL_TBOX_CSV_WRITER->WRITE_TO_STRING_TABLE
78 | * +-------------------------------------------------------------------------------------------------+
79 | * | [--->] I_TABLE TYPE ANY TABLE
80 | * | [<-()] R TYPE STRING_TABLE
81 | * | [!CX!] ZCX_TBOX_CSVMAN
82 | * +--------------------------------------------------------------------------------------
83 | METHOD write_to_string_table.
84 | DATA(csv_string) = write( i_table ).
85 |
86 | r = _to_string_table( csv_string ).
87 | ENDMETHOD.
88 |
89 | * ---------------------------------------------------------------------------------------+
90 | * | Instance Private Method ZCL_TBOX_CSV_WRITER->_APPLY_ESCAPINGS
91 | * +-------------------------------------------------------------------------------------------------+
92 | * | [<-->] C_VALUE TYPE STRING
93 | * +--------------------------------------------------------------------------------------
94 | METHOD _apply_escapings.
95 | IF m_general_params-escapechar IS INITIAL
96 | AND m_general_params-doublequote = abap_true
97 | AND m_general_params-quotechar IS NOT INITIAL.
98 | c_value = replace( val = c_value
99 | occ = 0
100 | sub = m_general_params-quotechar
101 | with = m_general_params-quotechar && m_general_params-quotechar ).
102 | ENDIF.
103 |
104 | IF m_general_params-escapechar IS NOT INITIAL
105 | AND m_general_params-quotechar IS NOT INITIAL.
106 | c_value = replace( val = c_value
107 | occ = 0
108 | sub = m_general_params-quotechar
109 | with = m_general_params-escapechar && m_general_params-quotechar ).
110 | ENDIF.
111 |
112 | IF m_general_params-escapechar IS NOT INITIAL
113 | AND ( m_general_params-quotechar IS INITIAL
114 | OR m_general_params-quoting = c_quote_none ).
115 | c_value = replace( val = c_value
116 | occ = 0
117 | sub = m_general_params-delimiter
118 | with = m_general_params-escapechar && m_general_params-delimiter ).
119 | ENDIF.
120 |
121 | IF m_general_params-escapechar IS NOT INITIAL.
122 | c_value = replace( val = c_value
123 | occ = 0
124 | sub = m_general_params-end_of_line
125 | with = m_general_params-escapechar && m_general_params-end_of_line ).
126 | ENDIF.
127 | ENDMETHOD.
128 |
129 | * ---------------------------------------------------------------------------------------+
130 | * | Instance Private Method ZCL_TBOX_CSV_WRITER->_APPLY_QUOTINGS
131 | * +-------------------------------------------------------------------------------------------------+
132 | * | [<-->] C_VALUE TYPE STRING
133 | * +--------------------------------------------------------------------------------------
134 | METHOD _apply_quotings.
135 | CASE m_general_params-quoting.
136 |
137 | WHEN c_quote_all.
138 | c_value = m_general_params-quotechar && c_value && m_general_params-quotechar.
139 |
140 | WHEN c_quote_minimal.
141 |
142 | IF find( val = c_value
143 | sub = m_general_params-delimiter ) >= 0
144 | OR find( val = c_value
145 | sub = m_general_params-end_of_line ) >= 0
146 | OR ( m_general_params-quotechar IS NOT INITIAL AND find( val = c_value
147 | sub = m_general_params-quotechar ) >= 0 ).
148 |
149 | c_value = m_general_params-quotechar && c_value && m_general_params-quotechar.
150 |
151 | ENDIF.
152 |
153 | WHEN c_quote_nonnumeric.
154 |
155 | IF m_current_field_obj->m_basic_type <> cl_abap_typedescr=>typekind_packed.
156 | c_value = m_general_params-quotechar && c_value && m_general_params-quotechar.
157 | ENDIF.
158 |
159 | ENDCASE.
160 | ENDMETHOD.
161 |
162 | * ---------------------------------------------------------------------------------------+
163 | * | Instance Public Method ZCL_TBOX_CSV_WRITER->_CREATE_CSV
164 | * +-------------------------------------------------------------------------------------------------+
165 | * | [--->] I_TABLE TYPE ANY TABLE
166 | * | [<-()] R_CSV TYPE STRING
167 | * +--------------------------------------------------------------------------------------
168 | METHOD _create_csv.
169 | LOOP AT i_table ASSIGNING FIELD-SYMBOL().
170 | DATA(tab_ix) = sy-tabix.
171 |
172 | LOOP AT m_fields_mapping INTO DATA(map).
173 | DATA(map_ix) = sy-tabix.
174 |
175 | m_current_field_obj = VALUE #( m_catalog[ field = map-field ]-field_obj OPTIONAL ).
176 | IF m_current_field_obj IS NOT BOUND.
177 | CONTINUE.
178 | ENDIF.
179 |
180 | ASSIGN COMPONENT map-field OF STRUCTURE TO FIELD-SYMBOL().
181 | IF sy-subrc <> 0.
182 | CONTINUE.
183 | ENDIF.
184 |
185 | DATA(val) = m_current_field_obj->_write( ).
186 |
187 | _apply_escapings( CHANGING c_value = val ).
188 | _apply_quotings( CHANGING c_value = val ).
189 |
190 | r_csv = r_csv && val.
191 |
192 | IF map_ix < lines( m_fields_mapping ).
193 | r_csv = r_csv && m_general_params-delimiter.
194 | ENDIF.
195 |
196 | ENDLOOP.
197 |
198 | IF tab_ix < lines( i_table ).
199 | r_csv = r_csv && m_general_params-end_of_line.
200 | ENDIF.
201 |
202 | ENDLOOP.
203 |
204 | IF m_general_params-header = abap_true.
205 | r_csv = _get_header( ) && m_general_params-end_of_line && r_csv.
206 | ENDIF.
207 | ENDMETHOD.
208 |
209 | * ---------------------------------------------------------------------------------------+
210 | * | Instance Private Method ZCL_TBOX_CSV_WRITER->_DEFAULT_CONFIG
211 | * +-------------------------------------------------------------------------------------------------+
212 | * +--------------------------------------------------------------------------------------
213 | METHOD _default_config.
214 | header( ).
215 | delimiter( `;` ).
216 | end_of_line( cl_abap_char_utilities=>cr_lf ).
217 | date_format( `dd.mm.yyyy` ).
218 | time_format( `hh:mm:ss` ).
219 | alignment( cl_abap_format=>a_left ).
220 | ENDMETHOD.
221 |
222 | * ---------------------------------------------------------------------------------------+
223 | * | Instance Private Method ZCL_TBOX_CSV_WRITER->_GET_HEADER
224 | * +-------------------------------------------------------------------------------------------------+
225 | * | [<-()] R TYPE STRING
226 | * +--------------------------------------------------------------------------------------
227 | METHOD _get_header.
228 | LOOP AT m_fields_mapping INTO DATA(map).
229 |
230 | DATA(field_obj) = VALUE #( m_catalog[ field = map-field ]-field_obj OPTIONAL ).
231 | IF field_obj IS NOT BOUND.
232 | CONTINUE.
233 | ENDIF.
234 |
235 | DATA(column_text) = COND #(
236 | WHEN field_obj->m_label IS NOT INITIAL
237 | THEN field_obj->m_label
238 | ELSE map-field ).
239 |
240 | DATA(val) = COND string(
241 | WHEN m_general_params-quotechar IS INITIAL
242 | THEN column_text
243 | ELSE |{ m_general_params-quotechar }{ column_text }{ m_general_params-quotechar }| ).
244 |
245 | r = COND #(
246 | WHEN r IS INITIAL
247 | THEN val
248 | ELSE |{ r }{ m_general_params-delimiter }{ val }| ).
249 |
250 | ENDLOOP.
251 | ENDMETHOD.
252 |
253 | * ---------------------------------------------------------------------------------------+
254 | * | Instance Private Method ZCL_TBOX_CSV_WRITER->_TO_STRING_TABLE
255 | * +-------------------------------------------------------------------------------------------------+
256 | * | [--->] I_CSV_STRING TYPE STRING
257 | * | [<-()] R TYPE STRING_TABLE
258 | * +--------------------------------------------------------------------------------------
259 | METHOD _to_string_table.
260 | IF m_general_params-escapechar IS INITIAL
261 | OR count( val = i_csv_string
262 | sub = m_general_params-escapechar && m_general_params-end_of_line ) <= 0.
263 |
264 | SPLIT i_csv_string AT m_general_params-end_of_line INTO TABLE r.
265 |
266 | RETURN.
267 |
268 | ENDIF.
269 |
270 | TRY.
271 | DATA(guid) = cl_system_uuid=>create_uuid_c22_static( ).
272 | CATCH cx_uuid_error.
273 | RETURN.
274 | ENDTRY.
275 |
276 | DATA(csv_string) = replace( val = i_csv_string
277 | occ = 0
278 | sub = m_general_params-escapechar && m_general_params-end_of_line
279 | with = guid ).
280 |
281 | SPLIT csv_string AT m_general_params-end_of_line INTO TABLE r.
282 |
283 | REPLACE ALL OCCURRENCES OF guid IN TABLE r WITH m_general_params-escapechar && m_general_params-end_of_line.
284 | ENDMETHOD.
285 | ENDCLASS.
286 |
--------------------------------------------------------------------------------
/src/zcl_tbox_csv_writer.clas.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ZCL_TBOX_CSV_WRITER
7 | E
8 | CSV Writer
9 | 1
10 | X
11 | X
12 | X
13 |
14 |
15 |
16 | M_CURRENT_FIELD_OBJ
17 | E
18 | CSV Manager | CSV Field
19 |
20 |
21 |
22 |
23 | WRITE
24 | ZCX_TBOX_CSVMAN
25 | E
26 | CSV Manager Exceptions
27 |
28 |
29 | WRITE_TO_STRING_TABLE
30 | R
31 | E
32 | Table of Strings
33 |
34 |
35 | WRITE_TO_STRING_TABLE
36 | ZCX_TBOX_CSVMAN
37 | E
38 | CSV Manager Exceptions
39 |
40 |
41 | _TO_STRING_TABLE
42 | R
43 | E
44 | Table of Strings
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/zcl_tbox_csvfield.clas.abap:
--------------------------------------------------------------------------------
1 | CLASS zcl_tbox_csvfield DEFINITION
2 | PUBLIC
3 | FINAL
4 | CREATE PRIVATE
5 |
6 | GLOBAL FRIENDS zcl_tbox_csv_common.
7 |
8 | PUBLIC SECTION.
9 | METHODS exclude
10 | IMPORTING i_active TYPE abap_bool DEFAULT abap_true
11 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csvfield.
12 |
13 | METHODS position
14 | IMPORTING i_position TYPE i
15 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csvfield.
16 |
17 | METHODS include
18 | IMPORTING i_active TYPE abap_bool DEFAULT abap_true
19 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csvfield.
20 |
21 | METHODS label
22 | IMPORTING i_label TYPE string
23 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csvfield.
24 |
25 | METHODS decimals
26 | IMPORTING i_decimals TYPE i
27 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csvfield.
28 |
29 | METHODS number_format
30 | IMPORTING i_number_format TYPE clike
31 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csvfield.
32 |
33 | METHODS time_format
34 | IMPORTING i_time_format TYPE clike
35 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csvfield.
36 |
37 | METHODS date_format
38 | IMPORTING i_date_format TYPE clike
39 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csvfield.
40 |
41 | METHODS country
42 | IMPORTING i_country TYPE land1
43 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csvfield.
44 |
45 | METHODS field_length
46 | IMPORTING i_field_length TYPE i
47 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csvfield.
48 |
49 | METHODS keep_init
50 | IMPORTING i_active TYPE abap_bool DEFAULT abap_true
51 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csvfield.
52 |
53 | METHODS alignment
54 | IMPORTING i_alignment TYPE i
55 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csvfield.
56 |
57 | METHODS condense_values
58 | IMPORTING i_active TYPE abap_bool DEFAULT abap_true
59 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csvfield.
60 |
61 | METHODS add_post_validation
62 | IMPORTING i_object_validator TYPE REF TO object OPTIONAL
63 | i_method_validator TYPE clike.
64 |
65 | METHODS add_pre_validation
66 | IMPORTING i_object_validator TYPE REF TO object OPTIONAL
67 | i_method_validator TYPE clike.
68 |
69 | METHODS _overflow
70 | IMPORTING i_value TYPE string
71 | RETURNING VALUE(r_fail) TYPE abap_bool.
72 |
73 | METHODS constructor
74 | IMPORTING i_csv TYPE REF TO zcl_tbox_csv_common
75 | i_name TYPE clike.
76 |
77 | PRIVATE SECTION.
78 | TYPES:
79 | BEGIN OF ts_validation,
80 | object_validator TYPE REF TO object,
81 | method_validator TYPE string,
82 | END OF ts_validation.
83 |
84 | DATA m_pre_validations TYPE STANDARD TABLE OF ts_validation.
85 | DATA m_post_validations TYPE STANDARD TABLE OF ts_validation.
86 | DATA m_csv TYPE REF TO zcl_tbox_csv_common.
87 | DATA m_field_name TYPE string.
88 | DATA m_basic_type TYPE abap_typekind.
89 | DATA m_format_params TYPE zcl_tbox_csv_common=>ts_format_params.
90 | DATA m_label TYPE string.
91 | DATA m_abort TYPE abap_bool.
92 |
93 | CONSTANTS c_initial_date TYPE string VALUE '00000000' ##NO_TEXT.
94 | CONSTANTS c_initial_time TYPE string VALUE '000000' ##NO_TEXT.
95 | CONSTANTS c_dec_separator_3 TYPE c LENGTH 1 VALUE 'Y' ##NO_TEXT.
96 | CONSTANTS c_dec_separator_2 TYPE c LENGTH 1 VALUE 'X' ##NO_TEXT.
97 | CONSTANTS c_dec_separator_1 TYPE c LENGTH 1 VALUE '' ##NO_TEXT.
98 |
99 | DATA m_element TYPE REF TO cl_abap_elemdescr.
100 | DATA m_field_length TYPE i.
101 | DATA m_decimals_set TYPE abap_bool.
102 |
103 | METHODS _set_basic_type
104 | IMPORTING i_basic_type TYPE abap_typekind.
105 |
106 | METHODS _write
107 | IMPORTING i_sap_value TYPE data
108 | RETURNING VALUE(r_csv_value) TYPE string.
109 |
110 | METHODS _read
111 | IMPORTING i_csv_value TYPE string
112 | RETURNING VALUE(r_sap_value) TYPE string
113 | RAISING zcx_tbox_csvman.
114 |
115 | METHODS _post_validations
116 | IMPORTING i_value TYPE string
117 | RAISING zcx_tbox_csvman.
118 |
119 | METHODS _pre_validations
120 | IMPORTING i_value TYPE string
121 | RAISING zcx_tbox_csvman.
122 |
123 | METHODS _basic_write
124 | IMPORTING i_sap_value TYPE string
125 | RETURNING VALUE(r_csv_value) TYPE string.
126 |
127 | METHODS _basic_read
128 | IMPORTING i_csv_value TYPE string
129 | RETURNING VALUE(r_sap_value) TYPE string.
130 |
131 | METHODS _write_char
132 | IMPORTING i_sap_value TYPE data
133 | RETURNING VALUE(r_csv_value) TYPE string.
134 |
135 | METHODS _read_char
136 | IMPORTING i_csv_value TYPE string
137 | RETURNING VALUE(r_sap_value) TYPE string.
138 |
139 | METHODS _write_date
140 | IMPORTING i_sap_value TYPE d
141 | RETURNING VALUE(r_csv_value) TYPE string.
142 |
143 | METHODS _read_date
144 | IMPORTING i_csv_value TYPE string
145 | RETURNING VALUE(r_sap_value) TYPE string.
146 |
147 | METHODS _write_time
148 | IMPORTING i_sap_value TYPE t
149 | RETURNING VALUE(r_csv_value) TYPE string.
150 |
151 | METHODS _read_time
152 | IMPORTING i_csv_value TYPE string
153 | RETURNING VALUE(r_sap_value) TYPE string.
154 |
155 | METHODS _write_numb
156 | IMPORTING i_sap_value TYPE numeric
157 | RETURNING VALUE(r_csv_value) TYPE string.
158 |
159 | METHODS _read_numb
160 | IMPORTING i_csv_value TYPE string
161 | RETURNING VALUE(r_sap_value) TYPE string.
162 |
163 | METHODS _transformation
164 | IMPORTING i_csv_value TYPE string
165 | RETURNING VALUE(r_sap_value) TYPE string.
166 |
167 | METHODS _assign_element
168 | IMPORTING i_element TYPE REF TO cl_abap_elemdescr.
169 |
170 | METHODS _get_field_length
171 | RETURNING VALUE(result) TYPE i.
172 |
173 | METHODS _get_country
174 | RETURNING VALUE(result) TYPE land1.
175 |
176 | METHODS _default_configuration.
177 |
178 | METHODS _get_decimals
179 | RETURNING VALUE(r) TYPE i.
180 |
181 | METHODS _invalid_number
182 | IMPORTING i_value TYPE string
183 | RETURNING VALUE(r_fail) TYPE abap_bool.
184 |
185 | METHODS _invalid_time
186 | IMPORTING i_value TYPE string
187 | RETURNING VALUE(r_fail) TYPE abap_bool.
188 |
189 | METHODS _invalid_date
190 | IMPORTING i_value TYPE string
191 | RETURNING VALUE(r_fail) TYPE abap_bool.
192 |
193 | METHODS _validation_time
194 | IMPORTING i_value TYPE string.
195 |
196 | METHODS _validation_date
197 | IMPORTING i_value TYPE string.
198 |
199 | METHODS _validation_number
200 | IMPORTING i_value TYPE string.
201 | ENDCLASS.
202 |
203 |
204 | CLASS zcl_tbox_csvfield IMPLEMENTATION.
205 | * ---------------------------------------------------------------------------------------+
206 | * | Instance Public Method ZCL_TBOX_CSVFIELD->ADD_POST_VALIDATION
207 | * +-------------------------------------------------------------------------------------------------+
208 | * | [--->] I_OBJECT_VALIDATOR TYPE REF TO OBJECT(optional)
209 | * | [--->] I_METHOD_VALIDATOR TYPE CLIKE
210 | * +--------------------------------------------------------------------------------------
211 | METHOD add_post_validation.
212 | INSERT VALUE #( object_validator = COND #( WHEN i_object_validator IS BOUND THEN i_object_validator ELSE me )
213 | method_validator = i_method_validator ) INTO TABLE m_post_validations.
214 | ENDMETHOD.
215 |
216 | * ---------------------------------------------------------------------------------------+
217 | * | Instance Public Method ZCL_TBOX_CSVFIELD->ADD_PRE_VALIDATION
218 | * +-------------------------------------------------------------------------------------------------+
219 | * | [--->] I_OBJECT_VALIDATOR TYPE REF TO OBJECT(optional)
220 | * | [--->] I_METHOD_VALIDATOR TYPE CLIKE
221 | * +--------------------------------------------------------------------------------------
222 | METHOD add_pre_validation.
223 | INSERT VALUE #( object_validator = COND #( WHEN i_object_validator IS BOUND THEN i_object_validator ELSE me )
224 | method_validator = i_method_validator ) INTO TABLE m_pre_validations.
225 | ENDMETHOD.
226 |
227 | * ---------------------------------------------------------------------------------------+
228 | * | Instance Public Method ZCL_TBOX_CSVFIELD->ALIGNMENT
229 | * +-------------------------------------------------------------------------------------------------+
230 | * | [--->] I_ALIGNMENT TYPE I
231 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSVFIELD
232 | * +--------------------------------------------------------------------------------------
233 | METHOD alignment.
234 | m_format_params-alignment = i_alignment.
235 |
236 | r = me.
237 | ENDMETHOD.
238 |
239 | * ---------------------------------------------------------------------------------------+
240 | * | Instance Public Method ZCL_TBOX_CSVFIELD->CONDENSE_VALUES
241 | * +-------------------------------------------------------------------------------------------------+
242 | * | [--->] I_ACTIVE TYPE ABAP_BOOL (default =ABAP_TRUE)
243 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSVFIELD
244 | * +--------------------------------------------------------------------------------------
245 | METHOD condense_values.
246 | m_format_params-condense = i_active.
247 |
248 | r = me.
249 | ENDMETHOD.
250 |
251 | * ---------------------------------------------------------------------------------------+
252 | * | Instance Public Method ZCL_TBOX_CSVFIELD->CONSTRUCTOR
253 | * +-------------------------------------------------------------------------------------------------+
254 | * | [--->] I_CSV TYPE REF TO ZCL_TBOX_CSV_COMMON
255 | * | [--->] I_NAME TYPE CLIKE
256 | * +--------------------------------------------------------------------------------------
257 | METHOD constructor.
258 | m_csv = i_csv.
259 | m_field_name = i_name.
260 |
261 | m_format_params = m_csv->m_format_params.
262 | m_decimals_set = m_csv->m_decimals_set.
263 |
264 | _default_configuration( ).
265 | ENDMETHOD.
266 |
267 | * ---------------------------------------------------------------------------------------+
268 | * | Instance Public Method ZCL_TBOX_CSVFIELD->COUNTRY
269 | * +-------------------------------------------------------------------------------------------------+
270 | * | [--->] I_COUNTRY TYPE LAND1
271 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSVFIELD
272 | * +--------------------------------------------------------------------------------------
273 | METHOD country.
274 | m_format_params-country = i_country.
275 |
276 | r = me.
277 | ENDMETHOD.
278 |
279 | * ---------------------------------------------------------------------------------------+
280 | * | Instance Public Method ZCL_TBOX_CSVFIELD->DATE_FORMAT
281 | * +-------------------------------------------------------------------------------------------------+
282 | * | [--->] I_DATE_FORMAT TYPE CLIKE
283 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSVFIELD
284 | * +--------------------------------------------------------------------------------------
285 | METHOD date_format.
286 | m_format_params-date_format = zcl_tbox_csv_common=>_create_date_format( i_date_format ).
287 |
288 | r = me.
289 | ENDMETHOD.
290 |
291 | * ---------------------------------------------------------------------------------------+
292 | * | Instance Public Method ZCL_TBOX_CSVFIELD->DECIMALS
293 | * +-------------------------------------------------------------------------------------------------+
294 | * | [--->] I_DECIMALS TYPE I
295 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSVFIELD
296 | * +--------------------------------------------------------------------------------------
297 | METHOD decimals.
298 | m_format_params-decimals = i_decimals.
299 | m_decimals_set = abap_true.
300 |
301 | r = me.
302 | ENDMETHOD.
303 |
304 | * ---------------------------------------------------------------------------------------+
305 | * | Instance Public Method ZCL_TBOX_CSVFIELD->EXCLUDE
306 | * +-------------------------------------------------------------------------------------------------+
307 | * | [--->] I_ACTIVE TYPE ABAP_BOOL (default =ABAP_TRUE)
308 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSVFIELD
309 | * +--------------------------------------------------------------------------------------
310 | METHOD exclude.
311 | IF i_active = abap_true AND NOT line_exists( m_csv->m_exclude_fields[ low = m_field_name ] ).
312 |
313 | INSERT VALUE #( sign = |I|
314 | option = |EQ|
315 | low = m_field_name ) INTO TABLE m_csv->m_exclude_fields.
316 |
317 | ELSEIF i_active = abap_false.
318 |
319 | DELETE m_csv->m_exclude_fields WHERE low = m_field_name.
320 |
321 | ENDIF.
322 |
323 | r = me.
324 | ENDMETHOD.
325 |
326 | * ---------------------------------------------------------------------------------------+
327 | * | Instance Public Method ZCL_TBOX_CSVFIELD->FIELD_LENGTH
328 | * +-------------------------------------------------------------------------------------------------+
329 | * | [--->] I_FIELD_LENGTH TYPE I
330 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSVFIELD
331 | * +--------------------------------------------------------------------------------------
332 | METHOD field_length.
333 | m_field_length = i_field_length.
334 |
335 | r = me.
336 | ENDMETHOD.
337 |
338 | * ---------------------------------------------------------------------------------------+
339 | * | Instance Public Method ZCL_TBOX_CSVFIELD->INCLUDE
340 | * +-------------------------------------------------------------------------------------------------+
341 | * | [--->] I_ACTIVE TYPE ABAP_BOOL (default =ABAP_TRUE)
342 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSVFIELD
343 | * +--------------------------------------------------------------------------------------
344 | METHOD include.
345 | IF i_active = abap_true AND NOT line_exists( m_csv->m_include_fields[ low = m_field_name ] ).
346 |
347 | INSERT VALUE #( sign = |I|
348 | option = |EQ|
349 | low = m_field_name ) INTO TABLE m_csv->m_include_fields.
350 |
351 | ELSEIF i_active = abap_false.
352 |
353 | DELETE m_csv->m_include_fields WHERE low = m_field_name.
354 |
355 | ENDIF.
356 |
357 | r = me.
358 | ENDMETHOD.
359 |
360 | * ---------------------------------------------------------------------------------------+
361 | * | Instance Public Method ZCL_TBOX_CSVFIELD->KEEP_INIT
362 | * +-------------------------------------------------------------------------------------------------+
363 | * | [--->] I_ACTIVE TYPE ABAP_BOOL (default =ABAP_TRUE)
364 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSVFIELD
365 | * +--------------------------------------------------------------------------------------
366 | METHOD keep_init.
367 | m_format_params-keep_init = i_active.
368 |
369 | r = me.
370 | ENDMETHOD.
371 |
372 | * ---------------------------------------------------------------------------------------+
373 | * | Instance Public Method ZCL_TBOX_CSVFIELD->LABEL
374 | * +-------------------------------------------------------------------------------------------------+
375 | * | [--->] I_LABEL TYPE STRING
376 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSVFIELD
377 | * +--------------------------------------------------------------------------------------
378 | METHOD label.
379 | m_label = i_label.
380 |
381 | r = me.
382 | ENDMETHOD.
383 |
384 | * ---------------------------------------------------------------------------------------+
385 | * | Instance Public Method ZCL_TBOX_CSVFIELD->NUMBER_FORMAT
386 | * +-------------------------------------------------------------------------------------------------+
387 | * | [--->] I_NUMBER_FORMAT TYPE CLIKE
388 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSVFIELD
389 | * +--------------------------------------------------------------------------------------
390 | METHOD number_format.
391 | m_format_params-number_format = i_number_format.
392 |
393 | r = me.
394 | ENDMETHOD.
395 |
396 | * ---------------------------------------------------------------------------------------+
397 | * | Instance Public Method ZCL_TBOX_CSVFIELD->POSITION
398 | * +-------------------------------------------------------------------------------------------------+
399 | * | [--->] I_POSITION TYPE I
400 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSVFIELD
401 | * +--------------------------------------------------------------------------------------
402 | METHOD position.
403 | IF line_exists( m_csv->m_fields_mapping[ field = m_field_name ] ).
404 |
405 | MODIFY TABLE m_csv->m_fields_mapping FROM VALUE #( field = m_field_name
406 | position = i_position ).
407 |
408 | ELSE.
409 |
410 | INSERT VALUE #( field = m_field_name
411 | position = i_position ) INTO TABLE m_csv->m_fields_mapping.
412 |
413 | ENDIF.
414 |
415 | r = me.
416 | ENDMETHOD.
417 |
418 | * ---------------------------------------------------------------------------------------+
419 | * | Instance Public Method ZCL_TBOX_CSVFIELD->TIME_FORMAT
420 | * +-------------------------------------------------------------------------------------------------+
421 | * | [--->] I_TIME_FORMAT TYPE CLIKE
422 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSVFIELD
423 | * +--------------------------------------------------------------------------------------
424 | METHOD time_format.
425 | m_format_params-time_format = zcl_tbox_csv_common=>_create_time_format( i_time_format ).
426 |
427 | r = me.
428 | ENDMETHOD.
429 |
430 | * ---------------------------------------------------------------------------------------+
431 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_ASSIGN_ELEMENT
432 | * +-------------------------------------------------------------------------------------------------+
433 | * | [--->] I_ELEMENT TYPE REF TO CL_ABAP_ELEMDESCR
434 | * +--------------------------------------------------------------------------------------
435 | METHOD _assign_element.
436 | m_element = i_element.
437 |
438 | DATA(basic_type) = zcl_tbox_csvman=>get_normalized_type( m_element->type_kind ).
439 |
440 | _set_basic_type( basic_type ).
441 | ENDMETHOD.
442 |
443 | * ---------------------------------------------------------------------------------------+
444 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_BASIC_READ
445 | * +-------------------------------------------------------------------------------------------------+
446 | * | [--->] I_CSV_VALUE TYPE STRING
447 | * | [<-()] R_SAP_VALUE TYPE STRING
448 | * +--------------------------------------------------------------------------------------
449 | METHOD _basic_read.
450 | r_sap_value = COND #( WHEN m_format_params-condense = abap_true THEN condense( i_csv_value ) ELSE i_csv_value ).
451 | ENDMETHOD.
452 |
453 | * ---------------------------------------------------------------------------------------+
454 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_BASIC_WRITE
455 | * +-------------------------------------------------------------------------------------------------+
456 | * | [--->] I_SAP_VALUE TYPE STRING
457 | * | [<-()] R_CSV_VALUE TYPE STRING
458 | * +--------------------------------------------------------------------------------------
459 | METHOD _basic_write.
460 | r_csv_value = i_sap_value.
461 | ENDMETHOD.
462 |
463 | * ---------------------------------------------------------------------------------------+
464 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_DEFAULT_CONFIGURATION
465 | * +-------------------------------------------------------------------------------------------------+
466 | * +--------------------------------------------------------------------------------------
467 | METHOD _default_configuration.
468 | IF m_format_params-alignment IS INITIAL.
469 | m_format_params-alignment = cl_abap_format=>a_left.
470 | ENDIF.
471 | ENDMETHOD.
472 |
473 | * ---------------------------------------------------------------------------------------+
474 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_GET_COUNTRY
475 | * +-------------------------------------------------------------------------------------------------+
476 | * | [<-()] RESULT TYPE LAND1
477 | * +--------------------------------------------------------------------------------------
478 | METHOD _get_country.
479 | result = COND #(
480 |
481 | WHEN m_format_params-use_number_format = abap_false THEN m_format_params-country
482 |
483 | WHEN m_format_params-number_format = c_dec_separator_1
484 | OR m_format_params-number_format = c_dec_separator_3 THEN `IT`
485 |
486 | WHEN m_format_params-number_format = c_dec_separator_2 THEN `US` ).
487 | ENDMETHOD.
488 |
489 | * ---------------------------------------------------------------------------------------+
490 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_GET_DECIMALS
491 | * +-------------------------------------------------------------------------------------------------+
492 | * | [<-()] R TYPE I
493 | * +--------------------------------------------------------------------------------------
494 | METHOD _get_decimals.
495 | r = COND #(
496 | WHEN m_decimals_set = abap_true
497 | THEN m_format_params-decimals
498 | ELSE m_element->decimals ).
499 | ENDMETHOD.
500 |
501 | * ---------------------------------------------------------------------------------------+
502 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_GET_FIELD_LENGTH
503 | * +-------------------------------------------------------------------------------------------------+
504 | * | [<-()] RESULT TYPE I
505 | * +--------------------------------------------------------------------------------------
506 | METHOD _get_field_length.
507 | result = COND #(
508 | WHEN m_field_length > 0
509 | THEN m_field_length
510 | ELSE m_element->output_length ).
511 | ENDMETHOD.
512 |
513 | * ---------------------------------------------------------------------------------------+
514 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_INVALID_DATE
515 | * +-------------------------------------------------------------------------------------------------+
516 | * | [--->] I_VALUE TYPE STRING
517 | * | [<-()] R_FAIL TYPE ABAP_BOOL
518 | * +--------------------------------------------------------------------------------------
519 | METHOD _invalid_date.
520 | r_fail = abap_true.
521 |
522 | IF NOT contains( val = i_value
523 | pcre = '^\d{8}$' ).
524 | RETURN.
525 | ENDIF.
526 |
527 | TRY.
528 | xco_cp_time=>date( iv_year = CONV #( i_value(4) )
529 | iv_month = CONV #( i_value+4(2) )
530 | iv_day = CONV #( i_value+6(2) ) ).
531 | CATCH cx_no_check.
532 | RETURN.
533 | ENDTRY.
534 |
535 | r_fail = abap_false.
536 | ENDMETHOD.
537 |
538 | * ---------------------------------------------------------------------------------------+
539 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_INVALID_NUMBER
540 | * +-------------------------------------------------------------------------------------------------+
541 | * | [--->] I_VALUE TYPE STRING
542 | * | [<-()] R_FAIL TYPE ABAP_BOOL
543 | * +--------------------------------------------------------------------------------------
544 | METHOD _invalid_number.
545 | r_fail = abap_true.
546 |
547 | IF count( val = i_value
548 | sub = `.` ) > 1.
549 | RETURN.
550 | ENDIF.
551 | IF count( val = i_value
552 | sub = `-` ) > 1.
553 | RETURN.
554 | ENDIF.
555 |
556 | DATA(sign_off) = find( val = i_value
557 | sub = `-` ).
558 | IF sign_off > 0 AND sign_off <> strlen( i_value ) - 1.
559 | RETURN.
560 | ENDIF.
561 |
562 | IF i_value CN '.-0123456789'.
563 | RETURN.
564 | ENDIF.
565 |
566 | r_fail = abap_false.
567 | ENDMETHOD.
568 |
569 | * ---------------------------------------------------------------------------------------+
570 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_INVALID_TIME
571 | * +-------------------------------------------------------------------------------------------------+
572 | * | [--->] I_VALUE TYPE STRING
573 | * | [<-()] R_FAIL TYPE ABAP_BOOL
574 | * +--------------------------------------------------------------------------------------
575 | METHOD _invalid_time.
576 | r_fail = abap_true.
577 |
578 | IF NOT contains( val = i_value
579 | pcre = '^\d{6}$' ).
580 | RETURN.
581 | ENDIF.
582 |
583 | TRY.
584 | xco_cp_time=>time( iv_hour = CONV #( i_value(2) )
585 | iv_minute = CONV #( i_value+2(2) )
586 | iv_second = CONV #( i_value+4(2) ) ).
587 | CATCH cx_no_check.
588 | RETURN.
589 | ENDTRY.
590 |
591 | r_fail = abap_false.
592 | ENDMETHOD.
593 |
594 | * ---------------------------------------------------------------------------------------+
595 | * | Instance Public Method ZCL_TBOX_CSVFIELD->_OVERFLOW
596 | * +-------------------------------------------------------------------------------------------------+
597 | * | [--->] I_VALUE TYPE STRING
598 | * | [<-()] R_FAIL TYPE ABAP_BOOL
599 | * +--------------------------------------------------------------------------------------
600 | METHOD _overflow.
601 | r_fail = abap_true.
602 |
603 | SPLIT i_value AT '.' INTO DATA(int) DATA(dec).
604 | int = replace( val = int occ = 0 sub = `-` with = ` ` ).
605 | CONDENSE int.
606 |
607 | IF strlen( int ) > m_element->length * 2 - 1 - m_element->decimals.
608 | RETURN.
609 | ENDIF.
610 |
611 | r_fail = abap_false.
612 | ENDMETHOD.
613 |
614 | * ---------------------------------------------------------------------------------------+
615 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_POST_VALIDATIONS
616 | * +-------------------------------------------------------------------------------------------------+
617 | * | [--->] I_VALUE TYPE STRING
618 | * | [!CX!] ZCX_TBOX_CSVMAN
619 | * +--------------------------------------------------------------------------------------
620 | METHOD _post_validations.
621 | DATA fail TYPE abap_bool.
622 |
623 | LOOP AT m_post_validations INTO DATA(post_val).
624 |
625 | CALL METHOD post_val-object_validator->(post_val-method_validator)
626 | EXPORTING i_value = i_value
627 | RECEIVING r_fail = fail.
628 |
629 | IF fail = abap_true.
630 |
631 | DATA(csv) = CAST zcl_tbox_csv_reader( m_csv ).
632 |
633 | csv->_add_validation_fail( i_check_failed = post_val-method_validator
634 | i_sap_value = i_value ).
635 |
636 | m_abort = abap_true.
637 | RETURN.
638 |
639 | ENDIF.
640 |
641 | ENDLOOP.
642 | ENDMETHOD.
643 |
644 | * ---------------------------------------------------------------------------------------+
645 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_PRE_VALIDATIONS
646 | * +-------------------------------------------------------------------------------------------------+
647 | * | [--->] I_VALUE TYPE STRING
648 | * | [!CX!] ZCX_TBOX_CSVMAN
649 | * +--------------------------------------------------------------------------------------
650 | METHOD _pre_validations.
651 | DATA fail TYPE abap_bool.
652 |
653 | LOOP AT m_pre_validations INTO DATA(pre_val).
654 |
655 | TRY.
656 | CALL METHOD pre_val-object_validator->(pre_val-method_validator)
657 | EXPORTING i_value = i_value
658 | RECEIVING r_fail = fail.
659 | CATCH cx_root INTO DATA(x_root).
660 | RAISE EXCEPTION NEW zcx_tbox_csvman( text = x_root->get_text( ) ).
661 | ENDTRY.
662 |
663 | IF fail = abap_true.
664 |
665 | DATA(csv) = CAST zcl_tbox_csv_reader( m_csv ).
666 | csv->_add_validation_fail( pre_val-method_validator ).
667 |
668 | m_abort = abap_true.
669 | RETURN.
670 |
671 | ENDIF.
672 |
673 | ENDLOOP.
674 | ENDMETHOD.
675 |
676 | * ---------------------------------------------------------------------------------------+
677 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_READ
678 | * +-------------------------------------------------------------------------------------------------+
679 | * | [--->] I_CSV_VALUE TYPE STRING
680 | * | [<-()] R_SAP_VALUE TYPE STRING
681 | * | [!CX!] ZCX_TBOX_CSVMAN
682 | * +--------------------------------------------------------------------------------------
683 | METHOD _read.
684 | CLEAR m_abort.
685 |
686 | _pre_validations( i_csv_value ).
687 |
688 | IF m_abort = abap_true.
689 | RETURN.
690 | ENDIF.
691 |
692 | DATA(sap_value) = _transformation( i_csv_value ).
693 |
694 | _post_validations( sap_value ).
695 |
696 | IF m_abort = abap_true.
697 | RETURN.
698 | ENDIF.
699 |
700 | r_sap_value = sap_value.
701 | ENDMETHOD.
702 |
703 | * ---------------------------------------------------------------------------------------+
704 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_READ_CHAR
705 | * +-------------------------------------------------------------------------------------------------+
706 | * | [--->] I_CSV_VALUE TYPE STRING
707 | * | [<-()] R_SAP_VALUE TYPE STRING
708 | * +--------------------------------------------------------------------------------------
709 | METHOD _read_char.
710 | r_sap_value = i_csv_value.
711 | ENDMETHOD.
712 |
713 | * ---------------------------------------------------------------------------------------+
714 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_READ_DATE
715 | * +-------------------------------------------------------------------------------------------------+
716 | * | [--->] I_CSV_VALUE TYPE STRING
717 | * | [<-()] R_SAP_VALUE TYPE STRING
718 | * +--------------------------------------------------------------------------------------
719 | METHOD _read_date.
720 | DATA(csv_value) = condense( i_csv_value ).
721 |
722 | IF csv_value IS INITIAL.
723 | r_sap_value = c_initial_date.
724 | RETURN.
725 | ENDIF.
726 |
727 | DATA internal_date TYPE c LENGTH 8.
728 |
729 | DATA(current_date) = cl_abap_context_info=>get_system_date( ).
730 |
731 | internal_date(4) = COND #(
732 | WHEN m_format_params-date_format-yy_len = 4
733 | THEN csv_value+m_format_params-date_format-yy_off(4)
734 | ELSE |{ current_date(2) }{ csv_value+m_format_params-date_format-yy_off(2) }| ).
735 |
736 | internal_date+4(2) = csv_value+m_format_params-date_format-mm_off(2).
737 | internal_date+6(2) = csv_value+m_format_params-date_format-dd_off(2).
738 |
739 | r_sap_value = internal_date.
740 |
741 | _validation_date( r_sap_value ).
742 | ENDMETHOD.
743 |
744 | * ---------------------------------------------------------------------------------------+
745 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_READ_NUMB
746 | * +-------------------------------------------------------------------------------------------------+
747 | * | [--->] I_CSV_VALUE TYPE STRING
748 | * | [<-()] R_SAP_VALUE TYPE STRING
749 | * +--------------------------------------------------------------------------------------
750 | METHOD _read_numb.
751 | IF i_csv_value IS INITIAL.
752 | r_sap_value = 0.
753 | RETURN.
754 | ENDIF.
755 |
756 | r_sap_value = i_csv_value.
757 |
758 | DATA(thousand_sep) = COND #(
759 | WHEN m_format_params-number_format = c_dec_separator_1 THEN '.'
760 | WHEN m_format_params-number_format = c_dec_separator_2 THEN ','
761 | WHEN m_format_params-number_format = c_dec_separator_3 THEN ' ' ).
762 |
763 | DATA(decimals_sep) = COND #(
764 | WHEN m_format_params-number_format = c_dec_separator_1 THEN ','
765 | WHEN m_format_params-number_format = c_dec_separator_2 THEN '.'
766 | WHEN m_format_params-number_format = c_dec_separator_3 THEN ',' ).
767 |
768 | IF thousand_sep IS NOT INITIAL.
769 | r_sap_value = replace( val = r_sap_value
770 | occ = 0
771 | sub = thousand_sep
772 | with = ` ` ).
773 | ENDIF.
774 |
775 | IF decimals_sep IS NOT INITIAL.
776 | r_sap_value = replace( val = r_sap_value
777 | occ = 0
778 | sub = decimals_sep
779 | with = `.` ).
780 | ENDIF.
781 |
782 | CONDENSE r_sap_value NO-GAPS.
783 |
784 | _validation_number( r_sap_value ).
785 | ENDMETHOD.
786 |
787 | * ---------------------------------------------------------------------------------------+
788 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_READ_TIME
789 | * +-------------------------------------------------------------------------------------------------+
790 | * | [--->] I_CSV_VALUE TYPE STRING
791 | * | [<-()] R_SAP_VALUE TYPE STRING
792 | * +--------------------------------------------------------------------------------------
793 | METHOD _read_time.
794 | DATA(csv_value) = condense( i_csv_value ).
795 |
796 | IF csv_value IS INITIAL.
797 | r_sap_value = c_initial_time.
798 | RETURN.
799 | ENDIF.
800 |
801 | DATA internal_time TYPE c LENGTH 6.
802 |
803 | internal_time(2) = csv_value+m_format_params-time_format-hh_off.
804 | internal_time+2(2) = csv_value+m_format_params-time_format-mm_off.
805 | internal_time+4(2) = csv_value+m_format_params-time_format-ss_off.
806 |
807 | r_sap_value = internal_time.
808 |
809 | _validation_time( r_sap_value ).
810 | ENDMETHOD.
811 |
812 | * ---------------------------------------------------------------------------------------+
813 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_SET_BASIC_TYPE
814 | * +-------------------------------------------------------------------------------------------------+
815 | * | [--->] I_BASIC_TYPE TYPE ABAP_TYPEKIND
816 | * +--------------------------------------------------------------------------------------
817 | METHOD _set_basic_type.
818 | m_basic_type = i_basic_type.
819 | ENDMETHOD.
820 |
821 | * ---------------------------------------------------------------------------------------+
822 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_TRANSFORMATION
823 | * +-------------------------------------------------------------------------------------------------+
824 | * | [--->] I_CSV_VALUE TYPE STRING
825 | * | [<-()] R_SAP_VALUE TYPE STRING
826 | * +--------------------------------------------------------------------------------------
827 | METHOD _transformation.
828 | DATA(basic_value) = _basic_read( i_csv_value ).
829 |
830 | r_sap_value = SWITCH #( m_basic_type
831 |
832 | WHEN cl_abap_typedescr=>typekind_char THEN _read_char( basic_value )
833 |
834 | WHEN cl_abap_typedescr=>typekind_date THEN _read_date( basic_value )
835 |
836 | WHEN cl_abap_typedescr=>typekind_time THEN _read_time( basic_value )
837 |
838 | WHEN cl_abap_typedescr=>typekind_packed THEN _read_numb( basic_value ) ).
839 | ENDMETHOD.
840 |
841 | * ---------------------------------------------------------------------------------------+
842 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_VALIDATION_DATE
843 | * +-------------------------------------------------------------------------------------------------+
844 | * | [--->] I_VALUE TYPE STRING
845 | * +--------------------------------------------------------------------------------------
846 | METHOD _validation_date.
847 | DATA(csv) = CAST zcl_tbox_csv_reader( m_csv ).
848 |
849 | IF _invalid_date( i_value ).
850 |
851 | csv->_add_validation_fail( i_check_failed = |INVALID_DATE|
852 | i_sap_value = i_value ).
853 |
854 | m_abort = abap_true.
855 |
856 | ENDIF.
857 | ENDMETHOD.
858 |
859 | * ---------------------------------------------------------------------------------------+
860 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_VALIDATION_NUMBER
861 | * +-------------------------------------------------------------------------------------------------+
862 | * | [--->] I_VALUE TYPE STRING
863 | * +--------------------------------------------------------------------------------------
864 | METHOD _validation_number.
865 | DATA(csv) = CAST zcl_tbox_csv_reader( m_csv ).
866 |
867 | IF _invalid_number( i_value ).
868 |
869 | csv->_add_validation_fail( i_check_failed = |INVALID_NUMBER|
870 | i_sap_value = i_value ).
871 |
872 | m_abort = abap_true.
873 | RETURN.
874 |
875 | ENDIF.
876 |
877 | IF _overflow( i_value ).
878 |
879 | csv->_add_validation_fail( i_check_failed = |OVERFLOW|
880 | i_sap_value = i_value ).
881 |
882 | m_abort = abap_true.
883 |
884 | ENDIF.
885 | ENDMETHOD.
886 |
887 | * ---------------------------------------------------------------------------------------+
888 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_VALIDATION_TIME
889 | * +-------------------------------------------------------------------------------------------------+
890 | * | [--->] I_VALUE TYPE STRING
891 | * +--------------------------------------------------------------------------------------
892 | METHOD _validation_time.
893 | DATA(csv) = CAST zcl_tbox_csv_reader( m_csv ).
894 |
895 | IF _invalid_time( i_value ).
896 |
897 | csv->_add_validation_fail( i_check_failed = |INVALID_TIME|
898 | i_sap_value = i_value ).
899 |
900 | m_abort = abap_true.
901 |
902 | ENDIF.
903 | ENDMETHOD.
904 |
905 | * ---------------------------------------------------------------------------------------+
906 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_WRITE
907 | * +-------------------------------------------------------------------------------------------------+
908 | * | [--->] I_SAP_VALUE TYPE DATA
909 | * | [<-()] R_CSV_VALUE TYPE STRING
910 | * +--------------------------------------------------------------------------------------
911 | METHOD _write.
912 | DATA(string_value) = SWITCH #( m_basic_type
913 |
914 | WHEN cl_abap_typedescr=>typekind_char THEN _write_char( i_sap_value )
915 |
916 | WHEN cl_abap_typedescr=>typekind_date THEN _write_date( i_sap_value )
917 |
918 | WHEN cl_abap_typedescr=>typekind_time THEN _write_time( i_sap_value )
919 |
920 | WHEN cl_abap_typedescr=>typekind_packed THEN _write_numb( i_sap_value ) ).
921 |
922 | r_csv_value = _basic_write( string_value ).
923 | ENDMETHOD.
924 |
925 | * ---------------------------------------------------------------------------------------+
926 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_WRITE_CHAR
927 | * +-------------------------------------------------------------------------------------------------+
928 | * | [--->] I_SAP_VALUE TYPE DATA
929 | * | [<-()] R_CSV_VALUE TYPE STRING
930 | * +--------------------------------------------------------------------------------------
931 | METHOD _write_char.
932 | r_csv_value = |{ i_sap_value WIDTH = _get_field_length( ) ALIGN = (m_format_params-alignment) }|.
933 |
934 | r_csv_value =
935 | COND #( WHEN m_format_params-condense = abap_true
936 | THEN condense( r_csv_value )
937 | ELSE r_csv_value ).
938 | ENDMETHOD.
939 |
940 | * ---------------------------------------------------------------------------------------+
941 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_WRITE_DATE
942 | * +-------------------------------------------------------------------------------------------------+
943 | * | [--->] I_SAP_VALUE TYPE D
944 | * | [<-()] R_CSV_VALUE TYPE STRING
945 | * +--------------------------------------------------------------------------------------
946 | METHOD _write_date.
947 | DATA c_date TYPE c LENGTH 10 VALUE '..........'.
948 |
949 | DATA(sap_value_str) = CONV string( i_sap_value ).
950 |
951 | IF sap_value_str = c_initial_date AND m_format_params-keep_init = abap_false.
952 | RETURN.
953 | ENDIF.
954 |
955 | IF sap_value_str IS INITIAL.
956 | RETURN.
957 | ENDIF.
958 |
959 | DATA(dd) = sap_value_str+6(2).
960 | DATA(mm) = sap_value_str+4(2).
961 | DATA(yy) = COND #( WHEN m_format_params-date_format-yy_len = 4 THEN sap_value_str(4) ELSE sap_value_str+2(2) ).
962 |
963 | c_date = replace( val = c_date
964 | off = m_format_params-date_format-dd_off
965 | len = 2
966 | with = dd ).
967 | c_date = replace( val = c_date
968 | off = m_format_params-date_format-mm_off
969 | len = 2
970 | with = mm ).
971 | c_date = replace( val = c_date
972 | off = m_format_params-date_format-yy_off
973 | len = m_format_params-date_format-yy_len
974 | with = yy ).
975 | c_date = replace( val = c_date
976 | occ = 0
977 | sub = ` `
978 | with = '0' ).
979 | c_date = replace( val = c_date
980 | occ = 0
981 | sub = '.'
982 | with = m_format_params-date_format-sep ).
983 |
984 | r_csv_value = c_date.
985 | ENDMETHOD.
986 |
987 | * ---------------------------------------------------------------------------------------+
988 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_WRITE_NUMB
989 | * +-------------------------------------------------------------------------------------------------+
990 | * | [--->] I_SAP_VALUE TYPE NUMERIC
991 | * | [<-()] R_CSV_VALUE TYPE STRING
992 | * +--------------------------------------------------------------------------------------
993 | METHOD _write_numb.
994 | DATA(country) = _get_country( ).
995 |
996 | DATA(csv_value) = |{ i_sap_value DECIMALS = _get_decimals( ) COUNTRY = country }|.
997 |
998 | IF m_format_params-use_number_format = abap_true
999 | AND m_format_params-number_format = c_dec_separator_3.
1000 |
1001 | csv_value = replace( val = csv_value
1002 | occ = 0
1003 | sub = `.`
1004 | with = ` ` ).
1005 |
1006 | ENDIF.
1007 |
1008 | r_csv_value = csv_value.
1009 |
1010 | IF i_sap_value = 0 AND m_format_params-keep_init = abap_false.
1011 | CLEAR r_csv_value.
1012 | ENDIF.
1013 | ENDMETHOD.
1014 |
1015 | * ---------------------------------------------------------------------------------------+
1016 | * | Instance Private Method ZCL_TBOX_CSVFIELD->_WRITE_TIME
1017 | * +-------------------------------------------------------------------------------------------------+
1018 | * | [--->] I_SAP_VALUE TYPE T
1019 | * | [<-()] R_CSV_VALUE TYPE STRING
1020 | * +--------------------------------------------------------------------------------------
1021 | METHOD _write_time.
1022 | DATA c_time TYPE c LENGTH 8 VALUE '........'.
1023 |
1024 | DATA(sap_value_str) = CONV string( i_sap_value ).
1025 |
1026 | IF sap_value_str = c_initial_time AND m_format_params-keep_init = abap_false.
1027 | RETURN.
1028 | ENDIF.
1029 |
1030 | IF sap_value_str IS INITIAL.
1031 | RETURN.
1032 | ENDIF.
1033 |
1034 | c_time = replace( val = c_time
1035 | off = m_format_params-time_format-hh_off
1036 | len = 2
1037 | with = sap_value_str(2) ).
1038 | c_time = replace( val = c_time
1039 | off = m_format_params-time_format-mm_off
1040 | len = 2
1041 | with = sap_value_str+2(2) ).
1042 | c_time = replace( val = c_time
1043 | off = m_format_params-time_format-ss_off
1044 | len = 2
1045 | with = sap_value_str+4(2) ).
1046 | c_time = replace( val = c_time
1047 | occ = 0
1048 | sub = ` `
1049 | with = '0' ).
1050 | c_time = replace( val = c_time
1051 | occ = 0
1052 | sub = '.'
1053 | with = m_format_params-time_format-sep ).
1054 |
1055 | r_csv_value = c_time.
1056 | ENDMETHOD.
1057 | ENDCLASS.
1058 |
--------------------------------------------------------------------------------
/src/zcl_tbox_csvfield.clas.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ZCL_TBOX_CSVFIELD
7 | E
8 | CSV Manager | CSV Field
9 | 1
10 | X
11 | X
12 | X
13 |
14 |
15 |
16 | M_CSV
17 | E
18 | CSV Manager | Common Methods
19 |
20 |
21 | M_ELEMENT
22 | E
23 | Runtime Type Services
24 |
25 |
26 |
27 |
28 | ALIGNMENT
29 | R
30 | E
31 | CSV Manager | CSV Field
32 |
33 |
34 | CONDENSE_VALUES
35 | R
36 | E
37 | CSV Manager | CSV Field
38 |
39 |
40 | CONSTRUCTOR
41 | I_CSV
42 | E
43 | CSV Manager | Common Methods
44 |
45 |
46 | COUNTRY
47 | I_COUNTRY
48 | E
49 | Country/Region Key
50 |
51 |
52 | COUNTRY
53 | R
54 | E
55 | CSV Manager | CSV Field
56 |
57 |
58 | DATE_FORMAT
59 | I_DATE_FORMAT
60 | E
61 | Country/Region Key
62 |
63 |
64 | DATE_FORMAT
65 | R
66 | E
67 | CSV Manager | CSV Field
68 |
69 |
70 | DECIMALS
71 | I_DECIMALS
72 | E
73 | Country/Region Key
74 |
75 |
76 | DECIMALS
77 | R
78 | E
79 | CSV Manager | CSV Field
80 |
81 |
82 | EXCLUDE
83 | R
84 | E
85 | CSV Manager | CSV Field
86 |
87 |
88 | FIELD_LENGTH
89 | R
90 | E
91 | CSV Manager | CSV Field
92 |
93 |
94 | INCLUDE
95 | R
96 | E
97 | CSV Manager | CSV Field
98 |
99 |
100 | KEEP_INIT
101 | R
102 | E
103 | CSV Manager | CSV Field
104 |
105 |
106 | LABEL
107 | R
108 | E
109 | CSV Manager | CSV Field
110 |
111 |
112 | NUMBER_FORMAT
113 | I_NUMBER_FORMAT
114 | E
115 | Country/Region Key
116 |
117 |
118 | NUMBER_FORMAT
119 | R
120 | E
121 | CSV Manager | CSV Field
122 |
123 |
124 | POSITION
125 | R
126 | E
127 | CSV Manager | CSV Field
128 |
129 |
130 | TIME_FORMAT
131 | I_TIME_FORMAT
132 | E
133 | Country/Region Key
134 |
135 |
136 | TIME_FORMAT
137 | R
138 | E
139 | CSV Manager | CSV Field
140 |
141 |
142 | _ASSIGN_ELEMENT
143 | I_ELEMENT
144 | E
145 | Runtime Type Services
146 |
147 |
148 | _GET_COUNTRY
149 | RESULT
150 | E
151 | Country Key
152 |
153 |
154 | _POST_VALIDATIONS
155 | ZCX_TBOX_CSVMAN
156 | E
157 | CSV Manager Exceptions
158 |
159 |
160 | _PRE_VALIDATIONS
161 | ZCX_TBOX_CSVMAN
162 | E
163 | CSV Manager Exceptions
164 |
165 |
166 | _READ
167 | ZCX_TBOX_CSVMAN
168 | E
169 | CSV Manager Exceptions
170 |
171 |
172 |
173 |
174 |
175 |
--------------------------------------------------------------------------------
/src/zcl_tbox_csvman.clas.abap:
--------------------------------------------------------------------------------
1 | CLASS zcl_tbox_csvman DEFINITION
2 | PUBLIC
3 | ABSTRACT
4 | CREATE PUBLIC.
5 |
6 | PUBLIC SECTION.
7 | CLASS-METHODS get_writer
8 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csv_writer.
9 |
10 | CLASS-METHODS get_reader
11 | RETURNING VALUE(r) TYPE REF TO zcl_tbox_csv_reader.
12 |
13 | CLASS-METHODS class_constructor.
14 |
15 | CLASS-METHODS get_normalized_type
16 | IMPORTING i_typekind TYPE clike
17 | RETURNING VALUE(r) TYPE abap_typekind.
18 |
19 | PROTECTED SECTION.
20 |
21 | PRIVATE SECTION.
22 | TYPES:
23 | BEGIN OF ts_typekind_normalization,
24 | typekind TYPE c LENGTH 1,
25 | normalized_type TYPE c LENGTH 1,
26 | END OF ts_typekind_normalization.
27 |
28 | CLASS-DATA g_typekinds_normalization TYPE TABLE OF ts_typekind_normalization WITH KEY typekind.
29 |
30 | CLASS-METHODS _load_typekinds.
31 | ENDCLASS.
32 |
33 |
34 | CLASS zcl_tbox_csvman IMPLEMENTATION.
35 | * ---------------------------------------------------------------------------------------+
36 | * | Static Public Method ZCL_TBOX_CSVMAN=>CLASS_CONSTRUCTOR
37 | * +-------------------------------------------------------------------------------------------------+
38 | * +--------------------------------------------------------------------------------------
39 | METHOD class_constructor.
40 | _load_typekinds( ).
41 | ENDMETHOD.
42 |
43 | * ---------------------------------------------------------------------------------------+
44 | * | Static Public Method ZCL_TBOX_CSVMAN=>GET_NORMALIZED_TYPE
45 | * +-------------------------------------------------------------------------------------------------+
46 | * | [--->] I_TYPEKIND TYPE CLIKE
47 | * | [<-()] R TYPE ABAP_TYPEKIND
48 | * +--------------------------------------------------------------------------------------
49 | METHOD get_normalized_type.
50 | r = VALUE #( g_typekinds_normalization[ typekind = i_typekind ]-normalized_type OPTIONAL ).
51 | ENDMETHOD.
52 |
53 | * ---------------------------------------------------------------------------------------+
54 | * | Static Public Method ZCL_TBOX_CSVMAN=>GET_READER
55 | * +-------------------------------------------------------------------------------------------------+
56 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSV_READER
57 | * +--------------------------------------------------------------------------------------
58 | METHOD get_reader.
59 | r = NEW #( ).
60 | ENDMETHOD.
61 |
62 | * ---------------------------------------------------------------------------------------+
63 | * | Static Public Method ZCL_TBOX_CSVMAN=>GET_WRITER
64 | * +-------------------------------------------------------------------------------------------------+
65 | * | [<-()] R TYPE REF TO ZCL_TBOX_CSV_WRITER
66 | * +--------------------------------------------------------------------------------------
67 | METHOD get_writer.
68 | r = NEW #( ).
69 | ENDMETHOD.
70 |
71 | * ---------------------------------------------------------------------------------------+
72 | * | Static Private Method ZCL_TBOX_CSVMAN=>_LOAD_TYPEKINDS
73 | * +-------------------------------------------------------------------------------------------------+
74 | * +--------------------------------------------------------------------------------------
75 | METHOD _load_typekinds.
76 | g_typekinds_normalization = VALUE #( ( typekind = cl_abap_typedescr=>typekind_char
77 | normalized_type = cl_abap_typedescr=>typekind_char )
78 | ( typekind = cl_abap_typedescr=>typekind_num
79 | normalized_type = cl_abap_typedescr=>typekind_char )
80 | ( typekind = cl_abap_typedescr=>typekind_numeric
81 | normalized_type = cl_abap_typedescr=>typekind_char )
82 | ( typekind = cl_abap_typedescr=>typekind_clike
83 | normalized_type = cl_abap_typedescr=>typekind_char )
84 | ( typekind = cl_abap_typedescr=>typekind_csequence
85 | normalized_type = cl_abap_typedescr=>typekind_char )
86 | ( typekind = cl_abap_typedescr=>typekind_simple
87 | normalized_type = cl_abap_typedescr=>typekind_char )
88 | ( typekind = cl_abap_typedescr=>typekind_string
89 | normalized_type = cl_abap_typedescr=>typekind_char )
90 | ( typekind = cl_abap_typedescr=>typekind_date
91 | normalized_type = cl_abap_typedescr=>typekind_date )
92 | ( typekind = cl_abap_typedescr=>typekind_time
93 | normalized_type = cl_abap_typedescr=>typekind_time )
94 | ( typekind = cl_abap_typedescr=>typekind_decfloat
95 | normalized_type = cl_abap_typedescr=>typekind_packed )
96 | ( typekind = cl_abap_typedescr=>typekind_decfloat16
97 | normalized_type = cl_abap_typedescr=>typekind_packed )
98 | ( typekind = cl_abap_typedescr=>typekind_decfloat34
99 | normalized_type = cl_abap_typedescr=>typekind_packed )
100 | ( typekind = cl_abap_typedescr=>typekind_float
101 | normalized_type = cl_abap_typedescr=>typekind_packed )
102 | ( typekind = cl_abap_typedescr=>typekind_packed
103 | normalized_type = cl_abap_typedescr=>typekind_packed )
104 | ( typekind = cl_abap_typedescr=>typekind_int
105 | normalized_type = cl_abap_typedescr=>typekind_packed )
106 | ( typekind = cl_abap_typedescr=>typekind_int1
107 | normalized_type = cl_abap_typedescr=>typekind_packed )
108 | ( typekind = cl_abap_typedescr=>typekind_int2
109 | normalized_type = cl_abap_typedescr=>typekind_packed )
110 | ( typekind = cl_abap_typedescr=>typekind_int8
111 | normalized_type = cl_abap_typedescr=>typekind_packed )
112 | ( typekind = cl_abap_typedescr=>typekind_hex
113 | normalized_type = cl_abap_typedescr=>typekind_char )
114 | ( typekind = cl_abap_typedescr=>typekind_xsequence
115 | normalized_type = cl_abap_typedescr=>typekind_char )
116 | ( typekind = cl_abap_typedescr=>typekind_xstring
117 | normalized_type = cl_abap_typedescr=>typekind_char ) ).
118 | ENDMETHOD.
119 | ENDCLASS.
120 |
--------------------------------------------------------------------------------
/src/zcl_tbox_csvman.clas.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ZCL_TBOX_CSVMAN
7 | E
8 | CSV Manager
9 | 1
10 | X
11 | X
12 | X
13 |
14 |
15 | -
16 |
17 | CO
18 |
19 | E
20 | E
21 | 0001
22 | X
23 | 00001
24 | R
25 |
26 |
27 | DOKU
28 | ZCL_TBOX_CSVMAN GET_WRITER
29 | CO
30 | E
31 | S_DOCU_SHOW
32 | S_DOCUS1
33 | 00001
34 | 072
35 |
36 |
37 |
38 | U1
39 | &FUNCTIONALITY&
40 |
41 |
42 | AS
43 | Get an instance of a CSV writer
44 |
45 |
46 | U1
47 |
48 |
49 | AS
50 |
51 |
52 | U1
53 |
54 |
55 | AS
56 |
57 |
58 | U1
59 |
60 |
61 | AS
62 |
63 |
64 | U1
65 |
66 |
67 | AS
68 |
69 |
70 | U1
71 |
72 |
73 | AS
74 |
75 |
76 |
77 |
78 |
79 |
80 | GET_READER
81 | R
82 | E
83 | CSV Writer
84 |
85 |
86 | GET_WRITER
87 | R
88 | E
89 | CSV Writer
90 |
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/src/zcl_tbox_csvman_apack.clas.abap:
--------------------------------------------------------------------------------
1 | CLASS zcl_tbox_csvman_apack DEFINITION
2 | PUBLIC
3 | FINAL
4 | CREATE PUBLIC .
5 |
6 | PUBLIC SECTION.
7 |
8 | INTERFACES zif_apack_manifest .
9 |
10 | METHODS constructor .
11 | PROTECTED SECTION.
12 | PRIVATE SECTION.
13 | ENDCLASS.
14 |
15 |
16 | CLASS zcl_tbox_csvman_apack IMPLEMENTATION.
17 |
18 |
19 | METHOD constructor.
20 |
21 | zif_apack_manifest~descriptor = VALUE #(
22 | group_id = 'ztbox'
23 | artifact_id = 'abap-tbox-csvman'
24 | version = '1.0'
25 | git_url = 'https://github.com/zenrosadira/abap-tbox-csvman.git' ).
26 |
27 | ENDMETHOD.
28 | ENDCLASS.
29 |
--------------------------------------------------------------------------------
/src/zcl_tbox_csvman_apack.clas.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ZCL_TBOX_CSVMAN_APACK
7 | E
8 | TBOX | CSV Manager APACK Metadata
9 | 1
10 | X
11 | X
12 | X
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/zcx_tbox_csvman.clas.abap:
--------------------------------------------------------------------------------
1 | CLASS zcx_tbox_csvman DEFINITION
2 | PUBLIC
3 | INHERITING FROM cx_static_check
4 | FINAL
5 | CREATE PUBLIC.
6 |
7 | PUBLIC SECTION.
8 | DATA m_text TYPE string.
9 |
10 | INTERFACES if_t100_message.
11 | INTERFACES if_t100_dyn_msg.
12 |
13 | METHODS constructor
14 | IMPORTING textid LIKE if_t100_message=>t100key OPTIONAL
15 | !previous LIKE previous OPTIONAL
16 | text TYPE string.
17 |
18 | PROTECTED SECTION.
19 |
20 | PRIVATE SECTION.
21 | ENDCLASS.
22 |
23 |
24 | CLASS zcx_tbox_csvman IMPLEMENTATION.
25 | METHOD constructor ##ADT_SUPPRESS_GENERATION.
26 | super->constructor( previous = previous ).
27 | CLEAR me->textid.
28 | IF textid IS INITIAL.
29 | if_t100_message~t100key = if_t100_message=>default_textid.
30 | ELSE.
31 | if_t100_message~t100key = textid.
32 | ENDIF.
33 | m_text = text.
34 | ENDMETHOD.
35 | ENDCLASS.
36 |
--------------------------------------------------------------------------------
/src/zcx_tbox_csvman.clas.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ZCX_TBOX_CSVMAN
7 | E
8 | CSV Manager Exceptions
9 | 40
10 | 1
11 | X
12 | X
13 | X
14 |
15 |
16 | -
17 |
18 | 00155DB5F7D41EDE81F31844E11B0321
19 | E
20 | 1
21 | CA==
22 |
23 |
24 |
25 | 00155DB5F7D41EDE81F31844E11B0321
26 | E
27 | 0001
28 | X
29 | R
30 | 255
31 | &TEXT&
32 |
33 |
34 |
35 |
36 |
37 |
38 | LIMU
39 |
40 | ZCX_TBOX_CSVMAN
41 | 00155DB5F7D41EDE81F31844E11B0321
42 | 0001
43 |
44 |
45 |
46 |
47 | LIMU
48 |
49 | ZCX_TBOX_CSVMAN
50 | 0001
51 |
52 |
53 |
54 |
55 | CONSTRUCTOR
56 | E
57 | CONSTRUCTOR
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------