diff --git a/docs/abap/extension-hooks.md b/docs/abap/extension-hooks.md index a00d297..a75655b 100644 --- a/docs/abap/extension-hooks.md +++ b/docs/abap/extension-hooks.md @@ -48,10 +48,11 @@ ENDMETHOD. turns a thrown exception into an `E` message, so the never‑raises contract still holds. - A **wrong‑typed** `hooks` object (one that does not implement `ZIF_SSI_HOOKS`) **fails the import closed** — configured hooks are never silently skipped. -- **Coverage:** all five hooks run on the **generic engine** (flat active create) and the facade. A - generated **deep/draft/upsert adapter** runs `coerce_field` / `on_before_persist` only when - regenerated with a hook‑aware `ZCL_SSI_ADAPTER_GEN` (`on_rows_parsed` / `on_message` / `on_completed` - always run — they sit in the facade). +- **Coverage:** the **generic engine** runs `coerce_field` / `on_before_persist` only; `on_rows_parsed` + / `on_message` / `on_completed` run in the **facade** (`zcl_ssi_import`) — so a direct + `get_importer->import` call gets only the two engine hooks. **No** generated adapter — flat, deep, or + upsert — runs `coerce_field` / `on_before_persist` today; that would require regenerating with a + hook‑aware `ZCL_SSI_ADAPTER_GEN`. Full reference + a runnable example: the [public API contract](public-api-contract.md#extension-hooks-zif_ssi_hooks) and the diff --git a/docs/abap/integration-guide.md b/docs/abap/integration-guide.md index 8c6b54d..5d592b1 100644 --- a/docs/abap/integration-guide.md +++ b/docs/abap/integration-guide.md @@ -55,7 +55,9 @@ ENDINTERFACE. iv_assoc = '_Items' iv_child_alias = 'Item' iv_parent_key = 'ROOTKEY' ). ``` Create that class in your package (~50 lines of typed EML that fills the create lines via - `ZCL_SSI_UTIL=>fill_line`, sets `%is_draft`, and returns the result). + `ZCL_SSI_UTIL=>fill_line` and returns the result). The **flat** and **upsert** generators set + `%is_draft` when `is_options-is_draft = abap_true`; `generate_deep` emits **ACTIVE‑CREATE only** + (draft + deep/composition is out of scope), so `is_draft` is ignored on the deep path. 2. **Register** it once at startup so the factory routes your BO to it: ```abap diff --git a/docs/abap/public-api-contract.md b/docs/abap/public-api-contract.md index 4d002bf..0e71b9c 100644 --- a/docs/abap/public-api-contract.md +++ b/docs/abap/public-api-contract.md @@ -37,7 +37,7 @@ Every public API below has a **runnable, copy‑pasteable example**, each proven | Object | Role | How a consumer uses it | |---|---|---| -| **`ZIF_SSI_TYPES`** | Shared types: `ts_options` (incl. `mode`, `hooks`), `ts_row`/`ts_cell`, `ts_result`/`ts_message`/`ts_key`, `tt_map`, the `gc_mode`/`gc_comp` enums | Reference the types in your own code | +| **`ZIF_SSI_TYPES`** | Shared types: `ts_options` (incl. `mode`, `hooks`), `ts_row`/`ts_cell`, `ts_result`/`ts_message`/`ts_key`, `tt_map`, the `gc_mode` enum | Reference the types in your own code | | **`ZIF_SSI_IMPORTER`** | The `import( it_rows is_options ) RETURNING rs_result` contract | The seam to **mock** the library (see [`test doubles`](#testing-against-the-library)) | | **`ZIF_SSI_HOOKS`** | Optional developer **extension hooks** — `on_rows_parsed` / `coerce_field` / `on_before_persist` / `on_message` / `on_completed` (all `DEFAULT IGNORE`) | Implement the ones you need; inject via `ts_options-hooks` (see [Extension hooks](#extension-hooks-zif_ssi_hooks)) | | **`ZCL_SSI_IMPORT`** | Facade — `import_file` (auto-detect xlsx/CSV) / `import_rows`. **Never raises** (errors → `ts_message`) | The simplest entry point | @@ -46,7 +46,7 @@ Every public API below has a **runnable, copy‑pasteable example**, each proven | **`ZCL_SSI_TEMPLATE`** | `build_create_template( iv_entity, iv_sample_rows, it_mapping )` | Generate an `.xlsx` CREATE template | | **`ZCL_SSI_ADAPTER_GEN`** | Code generators: `generate_flat` / `generate_deep` / `generate_upsert` / `generate_action` / `generate_template_function` | You **run** these to emit a typed adapter for your BO | | **`ZCL_SSI_FACTORY`** | `register( iv_entity, iv_class )` — register your adapter | Wire a generated adapter for an entity | -| **`ZCL_SSI_PARSER`** | `parse_xlsx` / `parse_csv` / `coerce` / `resolve_field` — stateless parsing utilities (`parse_xlsx` raises `zcx_ssi_parse`, see [Exceptions](#exceptions)) | Advanced/standalone parsing | +| **`ZCL_SSI_PARSER`** | `parse_xlsx` / `parse_csv` / `coerce` / `convexit_of` — stateless parsing utilities (`parse_xlsx` raises `zcx_ssi_parse`, see [Exceptions](#exceptions)) | Advanced/standalone parsing | | **Abstract & custom entities** — `ZSSI_A_IMPORT` · `ZSSI_A_IMPORT_FILE` · `ZSSI_A_FILE` · `ZSSI_A_RESULT` · `ZSSI_A_TEMPLATE` · `ZSSI_A_TFILE` · `ZSSI_C_TEMPLATE` | The action/function parameter & result shapes | Reference them in your BDEF `action`/`function` signatures | | **`ZSSI_IMPORTER`** (message class) | The translatable messages | Surfaced in `ts_message`; reference numbers if you map them | @@ -90,7 +90,7 @@ one‑line RAP delegate, inject hooks via the optional `is_options`: `%param` format fields override the base where supplied. Calling the importer **directly** (`zcl_ssi_factory=>get_importer` → `import`) bypasses the facade, so only the engine‑level hooks run there. `coerce_field` and `on_before_persist` are live on the **generic engine** (flat active -create); a generated **deep/draft/upsert adapter** gets them once regenerated with a `ZCL_SSI_ADAPTER_GEN` +create); no generated adapter (**flat, deep or upsert**) runs them today — an adapter gets them once regenerated with a `ZCL_SSI_ADAPTER_GEN` version that emits the calls (follow‑on). On the engine path `on_before_persist`'s instances table is anonymous (RTTC‑built) — navigate it with `ASSIGN COMPONENT` (incl. the `%CONTROL` flags) and mutate **in place**; a typed adapter passes its typed table. Worked examples: `ZCL_SSI_UNIT_HOOKS` (the library's own hook tests) and diff --git a/docs/abap/troubleshooting.md b/docs/abap/troubleshooting.md index 0f561b1..69a1072 100644 --- a/docs/abap/troubleshooting.md +++ b/docs/abap/troubleshooting.md @@ -9,7 +9,7 @@ | Opaque short dump on import | Lower‑case `entity_name`/`sub_name` in the dynamic EML | The component upper‑cases them; if you pass a BO/association name, give it uppercase | | Your validations don't run | `IN LOCAL MODE` was used (bypasses validations/auth/prechecks) | The component calls EML **non‑local** against your BO; don't enable a "local/privileged" mode unless you mean to | | Determination loops / times out | Your determination issues `MODIFY` that re‑triggers itself | Guard your determination (don't re‑modify the trigger field set); not a component issue | -| Dates all blank / wrong | Native Excel date cells or wrong format | Use **text** dates in the template (see [Options & data types](options.md)) | +| Dates all blank / wrong | Dates must be **text** in `YYYYMMDD` or `YYYY‑MM‑DD` form (an optional `Txx` time suffix is stripped); any other order (e.g. `31.12.2024`) or trailing junk is rejected | Fails **closed** with a per‑row conversion error (msg `002`, severity `E`) and the row is dropped — the value is never silently stored corrupt. Only calendar‑**range** checks apply (month `01`‑`12`, day `01`‑`31`), so an impossible date like Feb‑30 still passes and stores as‑is. See [Options & data types](options.md) | | Number‑range error `BEHAVIOR_ILLEGAL_STATEMENT` | Your BO's custom number range does its own `COMMIT WORK` | Set the number‑range object to **main‑memory buffering** | | Drafts created as active rows | No draft adapter registered for the BO | Generate + register a draft adapter — the generic engine is active‑only | | Big file slow / memory | XCO holds the workbook in memory; one huge commit | Lower `rowThreshold`, tune `chunk_size`; consider splitting the file | diff --git a/docs/abap/usage-cookbook.md b/docs/abap/usage-cookbook.md index 80f5313..1ac9134 100644 --- a/docs/abap/usage-cookbook.md +++ b/docs/abap/usage-cookbook.md @@ -57,7 +57,7 @@ zcl_ssi_parser=>coerce( ```abap " .xlsx whose header row = the importer's accepted fields, so the filled file -" re-imports with zero config. Raises cx_static_check for an unknown entity. +" re-imports with zero config. Returns an empty xstring for an unknown entity / one with no importable fields (never raises); check xstrlen( ) > 0. DATA(lv_xlsx) = zcl_ssi_template=>build_create_template( iv_entity = 'ZSSI_R_S_ORD' iv_sample_rows = 1 ). " xstrlen( lv_xlsx ) > 0 -> a valid .xlsx diff --git a/docs/ui5/pages/APIReference.md b/docs/ui5/pages/APIReference.md index 52f8be4..88ee833 100644 --- a/docs/ui5/pages/APIReference.md +++ b/docs/ui5/pages/APIReference.md @@ -2,7 +2,7 @@ ### Overview -The `spreadsheetimporter` component provides a way to import data from a spreadsheet into a table in the UI Builder application. +The `spreadsheetimporter` component provides a way to import data from a spreadsheet into a table in the UI5 application. ### Constructor diff --git a/docs/ui5/pages/Checks.md b/docs/ui5/pages/Checks.md index 604c889..ff38db5 100644 --- a/docs/ui5/pages/Checks.md +++ b/docs/ui5/pages/Checks.md @@ -20,4 +20,4 @@ The following types of errors are handled by the UI5 Spreadsheet Upload Control: - **Empty Headers** _(Available since: 1.2.0)_: The control checks if the uploaded spreadsheet contains empty headers (columns labeled "**EMPTY", "**EMPTY_1", etc.). These typically occur when Excel adds empty columns during import. When an empty header is detected, the control displays a warning message indicating the presence of empty columns and providing guidance on the expected start position for data. This check helps ensure data is properly aligned with column headers, especially when using custom start coordinates. This check can be disabled using the `skipEmptyHeadersCheck` configuration option. -- **Nullable Field Violations** _(Available since: [Next Release])_: The control validates null values against OData metadata. When you use the `__NULL__` marker in a cell to explicitly set a field to NULL, the component checks the field's Nullable attribute in the OData metadata. If the field is non-nullable (Nullable="false"), an error is displayed. This validation ensures data integrity and prevents backend errors. Key fields and mandatory fields are typically non-nullable. See [Null & Empty Value Handling](NullHandling.md) for comprehensive guide. +- **Nullable Field Violations** _(Available since: 2.4.0)_: The control validates null values against OData metadata. When you use the `__NULL__` marker in a cell to explicitly set a field to NULL, the component checks the field's Nullable attribute in the OData metadata. If the field is non-nullable (Nullable="false"), an error is displayed. This validation ensures data integrity and prevents backend errors. Key fields and mandatory fields are typically non-nullable. See [Null & Empty Value Handling](NullHandling.md) for comprehensive guide. diff --git a/docs/ui5/pages/Configuration.md b/docs/ui5/pages/Configuration.md index aa71fde..6de5624 100644 --- a/docs/ui5/pages/Configuration.md +++ b/docs/ui5/pages/Configuration.md @@ -37,7 +37,7 @@ The table below summarizes the options available for the UI5 Spreadsheet Importe | [`batchSize`](#batchsize) | Controls the size of batches sent to the backend. | `1000` | 0.11.0 | `number` | | [`strict`](#strict) | Controls availability of the "Continue" button in error dialogs. | `false` | 0.16.0 | `boolean` | | [`decimalSeparator`](#decimalseparator) | Sets the decimal separator for numbers. | Browser default | 0.17.0 | `string` | -| docs: | [`nullMarker`](#nullmarker) | Marker string for NULL values in Excel cells. | `'__NULL__'` | 2.4.0 | `string` | +| [`nullMarker`](#nullmarker) | Marker string for NULL values in Excel cells. | `'__NULL__'` | 2.4.0 | `string` | | [`emptyStringMarker`](#emptystringmarker) | Marker string for empty strings (text fields only). | `'__EMPTY__'` | 2.4.0 | `string` | | [`mandatoryFields`](#mandatoryfields) | Specifies mandatory fields to check in the spreadsheet. | Not defined | 0.15.0 | `string[]` | | [`skipMandatoryFieldCheck`](#skipmandatoryfieldcheck) | Skips the check for mandatory fields. | `false` | 0.17.0 | `boolean` | @@ -96,8 +96,7 @@ The `directUploadConfig` option enables direct file upload to a CAP backend usin useCdsPlugin: true, localhostSupport: true, localhostPort: 4004, - csrf: true, - uploadTimeout: 30000 + useCsrf: true }, componentContainerData:{ buttonText:'Excel Upload with CDS Plugin', diff --git a/docs/ui5/pages/Events.md b/docs/ui5/pages/Events.md index 28b9454..3ef565c 100644 --- a/docs/ui5/pages/Events.md +++ b/docs/ui5/pages/Events.md @@ -76,7 +76,7 @@ You can add errors to the `messages` property of the `SpreadsheetUpload` control - `row` - the row number of the error - `group` - set to `true` or `false` to group the errors by title - `rawValue` - the raw value of the data from the spreadsheet -- `ui5type` - the type of the error, can be `Error`, `Warning`, `Success`, `Information` or `None` from the [`MessageType](https://ui5.sap.com/#/api/sap.ui.core.MessageType) enum +- `ui5type` - the type of the error, can be `Error`, `Warning`, `Success`, `Information` or `None` from the [`MessageType`](https://ui5.sap.com/#/api/sap.ui.core.MessageType) enum Errors with the same title will be grouped. diff --git a/docs/ui5/pages/HowItWorks.md b/docs/ui5/pages/HowItWorks.md index db59229..d137470 100644 --- a/docs/ui5/pages/HowItWorks.md +++ b/docs/ui5/pages/HowItWorks.md @@ -12,7 +12,7 @@ When the component is centrally deployed on an ABAP server, the setup is straigh ## Integration into UI5 Integrating the component is straightforward as long as the component has access to the context or the view, as without this access, it won't function. -Upon creation of the component, it searches for a table in the view to utilize the binding for the upload. Other necessary details, such as metadata and draft activation actions, are also derived from the table. If no table or more than two tables are found, the table must be defined in the options. +Upon creation of the component, it searches for a table in the view to utilize the binding for the upload. Other necessary details, such as metadata and draft activation actions, are also derived from the table. If no table or more than one table are found, the table must be defined in the options. ## Creating the Template File diff --git a/docs/ui5/pages/NullHandling.md b/docs/ui5/pages/NullHandling.md index 8a3e169..997f959 100644 --- a/docs/ui5/pages/NullHandling.md +++ b/docs/ui5/pages/NullHandling.md @@ -63,7 +63,7 @@ The component will send these requests to your backend: { "ID": "789", "email": "", "notes": null } ``` -Notice how empty cells in the Name and Phone columns don't appear in the JSON at all. This means those fields remain unchanged on the backend. +Notice how empty cells in the Name, Email, and Notes columns don't appear in the JSON at all. This means those fields remain unchanged on the backend. ## Validation Rules diff --git a/docs/ui5/pages/Wizard.md b/docs/ui5/pages/Wizard.md index e491755..c719035 100644 --- a/docs/ui5/pages/Wizard.md +++ b/docs/ui5/pages/Wizard.md @@ -115,7 +115,7 @@ openWizard: async function () { You can pass configuration options to override component settings: ```javascript -openWizard: function () { +openWizard: async function () { this.spreadsheetUpload = await this.getView() .getController() .getOwnerComponent() @@ -137,7 +137,7 @@ openWizard: function () { debug: true // Enable debug mode }; - oComponent.openWizard(wizardOptions) + this.spreadsheetUpload.openWizard(wizardOptions); } ``` @@ -147,13 +147,13 @@ The wizard supports all standard [events](Events.md): ```javascript // Attach events before opening wizard -oComponent.attachUploadButtonPress(function (event) { +this.spreadsheetUpload.attachUploadButtonPress(function (event) { // Handle upload completion const payload = event.getParameter('payload'); console.log('Data uploaded:', payload); }); -oComponent.attachCheckBeforeRead(function (event) { +this.spreadsheetUpload.attachCheckBeforeRead(function (event) { // Validate data before processing const sheetData = event.getParameter('sheetData'); // Add custom validation logic diff --git a/docs/ui5/pages/spreadsheetdownload.md b/docs/ui5/pages/spreadsheetdownload.md index fccc0c3..613bdec 100644 --- a/docs/ui5/pages/spreadsheetdownload.md +++ b/docs/ui5/pages/spreadsheetdownload.md @@ -24,11 +24,11 @@ This means that you can download all Orders, including the OrderItems, ShippingI | Option | Description | Default | Type | | ----------------- | ----------------------------------------------- | ----------- | --------------- | | `addKeysToExport` | Adds keys to the export file | `false` | boolean | -| `setDraftStatus` | Sets the draft status in `IsActiveEntity` | `false` | boolean | +| `setDraftStatus` | Sets the draft status in `IsActiveEntity` | `true` | boolean | | `filename` | Defines the filename for the export file | Entity Name | string | | `deepExport` | Turn on to export of sibling entities | `false` | boolean | | `deepLevel` | Defines the level of sibling entities to export | `0` | number | -| `showOptions` | Shows options dialog for users | `false` | boolean | +| `showOptions` | Shows options dialog for users | `true` | boolean | | `columns` | Defines the columns to export | `{}` | object or array | ### Sample Usage