You can use a ViewModel seeker to search, export, and create or update model data from tab-separated rows, including data copied from Excel; this page is for developers designing that shared behavior in MDriven Designer and MDriven Turnkey.
What convergence means
Convergence is the use of one seeker ViewModel definition for several tabular-data workflows. The same definition can support:
- Finding several values at once.
- Updating existing objects from tab-separated input.
- Creating objects when an imported key is not found.
- Assigning single links through combo box columns.
- Moving data between an Excel selection and a Turnkey seeker through the MDriven Turnkey Excel Plugin.
- Supplying tabular data to a receiving system as part of a controlled synchronization design.
The ViewModel remains the contract: it defines which data is exposed, which columns can be written, and how a row finds an existing object. This means the same modeled rules and authorization-controlled views apply when data is handled through the supported ViewModel clients, including Turnkey, WPF, the debugger, generated ViewModels, and server-side ViewModels in MDrivenServer.
How a tab-separated import works
The seeker input accepts rows where values are separated by tab characters. The first column is always the lookup key. The remaining columns correspond, from left to right, to columns in the seeker result grid.
For example, a seeker whose first result column is Guid and whose second result column is an editable Name column can receive:
793e00a1-7e61-4261-a2ed-7e9047e2c5c4 My new value 1
6d47193c-e4b9-486b-827d-104e01466a81 My new value 2
f084a714-2ae6-43a5-8862-74c912861aae My new value 3
For each row, the seeker searches for the value in the first column using its configured search criteria. If it finds an object, it writes the supplied values to writable result columns. A read-only column is skipped.
Configure an import seeker
Create an unrooted seeker ViewModel. An unrooted ViewModel searches for objects rather than starting from one specified root object; see rooted and unrooted ViewModels.
- Define the seeker so its search criteria can find an existing object from the first result column. Choose a stable key that identifies the object you intend to update.
- Place that key in the leftmost column of the seeker result grid.
- Add each attribute or single link that you want to receive as a following result-grid column.
- Mark every column that must receive imported data as writable. Columns are commonly created as read-only; read-only columns do not receive values.
- Make the default seeker field,
vSeekParam, multi-line. A multi-line field accepts the line breaks and tab characters produced when users copy a rectangular range from Excel. - If missing keys should create objects, add an action named
CreateNew. The action must create an object of the same class as the objects in the result list and set up the key needed by the seeker. It must be a ViewModel or class action, not only an action defined in the Action Editor. - Run the seeker and paste tab-separated rows into the seeker field. Execute the search/import operation, then save the changed data when the client presents Save/Cancel.
Update versus create
If a row key is found, the row updates that object. If the key is not found, the import logic looks for CreateNew.
For example, if none of these GUIDs exists:
77777777-7e61-4261-a2ed-7e9047e2c5c4 My new value 4
88888888-e4b9-486b-827d-104e01466a81 My new value 5
99999999-2ae6-43a5-8862-74c912861aae My new value 6
and CreateNew is available, the seeker creates result objects and writes each row's writable values. If CreateNew is not available, a missing key cannot produce a new object.
Importing one column
Each input row must contain a tab character. Take particular care when importing a single value per row: include a tab character in each line. Set columns that must not be changed to read-only.
Set single links with combo boxes
Use a combo box result column when an import must set a single association rather than a scalar attribute. The imported text is string-matched to find the appropriate object, then the link is assigned.
For example, if a Product seeker has a writable Supplier combo box column, an input row can contain the product key followed by a supplier name:
P-10025 Northwind Supplies
Design the combo box so its displayed or evaluated value identifies the intended related object. This avoids requiring users to import internal object identities to set a single link.
Key parameter types
The standard seeker parameter is vSeekParam : String. When the lookup key is a GUID or integer, define the corresponding additional variable so the seeker can use a correctly typed value before its OCL/PS query is translated to SQL.
| Variable | Type | When to define it |
|---|---|---|
vSeekParam
|
String | Standard seeker parameter. Define it for the textual search input. |
vSeekParamAsGuid
|
Guid | Define it when the first-column key is a GUID. It is populated before search when the input parses as a GUID. |
vSeekParamAsInt
|
Integer | Define it when the first-column key is an integer. It is populated before search when the input parses as an integer. |
For example, a seeker that compares a GUID model attribute should use vSeekParamAsGuid in the relevant OCL search expression rather than comparing the GUID attribute directly with the string vSeekParam. This prevents SQL type-comparison errors.
Multi-value and tolerant search
The seeker search logic also helps users find data when a normal search produces no result.
| Input condition after normal search has no hits | Fallback behavior | Example |
|---|---|---|
| Input contains spaces | The logic tries a wildcard form, replacing spaces with wildcards. This requires the seeker search expression to use SQL-like matching. | Banana box linnen can be tried as Banana%box%linnen, which can find Banana box with linnen lining.
|
| The wildcard attempt still has no hits | The logic splits the input on spaces and searches for individual words. | Banana box linnen is split into individual word searches.
|
| Input contains semicolons and earlier logic has no hits | The logic can split the input on semicolons, search each value, and build a combined result set. | A-100;A-200;A-300 can find the three values through separate searches.
|
These fallbacks occur only after the normal seeker logic has found no results. Do not rely on them as a substitute for defining clear search expressions and a suitable import key.
Use the same seeker with Excel
With the MDriven Turnkey Excel Plugin installed, an Excel selection can exchange data with the first grid in a Turnkey view. For the full installation and user workflow, see Documentation:Excel Plugin Function.
To write an Excel range into a Turnkey seeker:
- Open the Turnkey view that hosts the configured seeker.
- In Excel, select a rectangular range. Put the seeker key in the leftmost Excel column and place values for writable result columns to its right.
- Use Write Selected to Turnkey in the Excel plugin.
- The plugin seeks each leftmost-column value, updates writable columns for matches, and invokes
CreateNewfor missing keys when that action is available. - Review the changes in Turnkey and use its Save/Cancel controls to commit or discard them.
To find data from Excel, select cells and use Seek Selected in Turnkey. Each selected value is sought and matching objects accumulate in the seeker result grid. To export, use the plugin's data command to place the first Turnkey grid into the selected Excel cell.
The plugin works against the data and columns designed in the Turnkey view. It does not bypass the modeled view or its access control.
Apply the pattern to synchronization
Use compatible sending and receiving ViewModels when you need to move selected data between MDriven systems. Define explicitly what each system sends, what it receives, and in which direction; do not treat synchronization as an automatic attempt to reconcile every object in two models.
A receiving system exposes one or more import seekers configured as described on this page. A sending system prepares matching tabular rows, sets the receiver's vSeekParam to that data, executes the receiver search/import, and saves. Divide data into multiple ViewModels when different object types or relationships require separate row contracts.
For example, synchronize product master data through one seeker keyed by product number, then synchronize supplier assignments through a separate seeker with a writable Supplier combo box. This makes the data movement visible in the model and keeps each import key and relationship rule explicit.
Related import and export patterns
This page describes the shared seeker-based tabular pattern. Use the specialized documentation for other sources and destinations:
- HowTos:Import Tabular Separated Data Using OCLOperators describes invoking the tab-separated import behavior with
selfVM.ImportTabSepData. - Training:Import data from other SQL servers describes an MDrivenServer job that reads an external SQL-based system and maps results through an import ViewModel or nesting.
- Documentation:MDriven Designer and Modlr extensions–exporting data describes exporting grids from MDriven Designer and Modlr extensions.
- Documentation:Import Data is retained as older background; use this page for the current seeker-based approach.
Import tab-separated data: first steps
You can import rows copied from Excel to create or update objects with a seeker ViewModel; this workflow is for developers who are new to tab-separated import.
A seeker ViewModel is a ViewModel that searches for objects by criteria. For import, the search criteria decides whether the value in each row's first column identifies an existing object.
Prepare the seeker ViewModel
- Declare a seeker ViewModel for the class you want to import.
- Make the first search-result column the key that the seeker searches for. For example, use
Thing.Guidas the first column when each imported row starts with a Guid. - Add the columns that should receive imported values. Make each column that you want to write editable in the search-result grid.
- Make the default search field,
vSeekParam, multi-line. It must accept tabs and multiple lines from clipboard data. - If missing keys should create objects, add a ViewModel action named
CreateNewthat creates an object of the seeker class.
Paste and import rows
Copy tab-separated rows from Excel or another source, paste them into the multi-line search field, and execute the seeker search.
| Imported column | Meaning |
|---|---|
| First column | The key. The seeker uses its search criteria to find an existing object. |
| Following columns | Values to write to the editable search-result columns. |
For example, when the seeker searches Thing.Guid and the next column is an editable value, paste:
793e00a1-7e61-4261-a2ed-7e9047e2c5c4 My new value 1
6d47193c-e4b9-486b-827d-104e01466a81 My new value 2
The import finds each Thing by Guid and writes the value from the second column. If a key is not found and the seeker has a CreateNew action, the import calls that action and adds the new object to the search result.
Know what the import changes
- A read-only column is skipped. Make a column editable when it must receive an imported value.
- A Combobox column performs string matching to find the object for a single link.
- The first column is always the key. Do not place an ordinary value before the key.
- When the key is a Guid, define
vSeekParamAsGuid : Guidif the seeker needs a Guid parameter. When the key is an integer, definevSeekParamAsInt : Integer. The import fills either variable before the search when it exists and the key can be parsed.
This seeker-based import works in Turnkey, the debugger, code-generated ViewModels, WPF, and server-side ViewModels in MDriven Server.
The Solution
An example seeker ViewModel configuration:
The seeker displays search results in a grid:
The import logic determines whether to update or create:
Combo box columns resolve imported text to associations:
Understand how different column types handle imported data:
Download ImportTabSepExample:
A working example model is available for download: File:ImportTabSepExample.modlr
