excel-list-transform 1.1__tar.gz → 1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {excel_list_transform-1.1 → excel_list_transform-1.3}/PKG-INFO +111 -15
- {excel_list_transform-1.1 → excel_list_transform-1.3}/README.md +8 -4
- excel_list_transform-1.1/excel_list_transform.egg-info/PKG-INFO → excel_list_transform-1.3/README_pypi.md +99 -37
- excel_list_transform-1.1/README_pypi.md → excel_list_transform-1.3/excel_list_transform.egg-info/PKG-INFO +133 -9
- {excel_list_transform-1.1 → excel_list_transform-1.3}/excel_list_transform.egg-info/SOURCES.txt +3 -0
- excel_list_transform-1.3/excel_list_transform.egg-info/requires.txt +10 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/pyproject.toml +2 -2
- {excel_list_transform-1.1 → excel_list_transform-1.3}/setup.py +12 -7
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/config_enums.py +17 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/config_excel_list_transform.py +46 -24
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/config_read_old.py +4 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/config_xls_list_transf_name.py +9 -4
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/config_xls_list_transf_num.py +8 -4
- excel_list_transform-1.3/src/excel_list_transform/edit_cfg.py +150 -0
- excel_list_transform-1.3/src/excel_list_transform/edit_descriptions.py +336 -0
- excel_list_transform-1.3/src/excel_list_transform/file_extension.py +28 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/generate_cfg.py +18 -16
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/generate_txt.py +52 -4
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/handle_tableio.py +10 -2
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/num_named_conversion.py +13 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/rewrite_value.py +8 -6
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/row_split_merge.py +64 -80
- excel_list_transform-1.3/src/excel_list_transform/split_parts.py +56 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/transform_cmd.py +40 -1
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/transform_func_common.py +32 -19
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/transform_func_named.py +31 -7
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/transform_func_num.py +1 -3
- excel_list_transform-1.3/src/excel_list_transform/version_information.py +52 -0
- excel_list_transform-1.1/excel_list_transform.egg-info/requires.txt +0 -5
- excel_list_transform-1.1/src/excel_list_transform/file_extension.py +0 -30
- excel_list_transform-1.1/src/excel_list_transform/version_information.py +0 -32
- {excel_list_transform-1.1 → excel_list_transform-1.3}/LICENSE.txt +0 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/excel_list_transform.egg-info/dependency_links.txt +0 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/excel_list_transform.egg-info/top_level.txt +0 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/setup.cfg +0 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/__init__.py +0 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/__main__.py +0 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/check_indata_common.py +0 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/commontypes.py +0 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/config_match.py +0 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/file_must_exist.py +0 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/handle_empty_column.py +0 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/migrate_cfg.py +0 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/migrate_cfg_warn_hook.py +0 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/py.typed +0 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/recode.py +0 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/str_to_enum.py +0 -0
- {excel_list_transform-1.1 → excel_list_transform-1.3}/src/excel_list_transform/transform_func.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: excel-list-transform
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3
|
|
4
4
|
Summary: Transform table data with configurable row and column changes.
|
|
5
5
|
Author: Tom Björkholm
|
|
6
6
|
Author-email: Tom Björkholm <klausuler_linnet0q@icloud.com>
|
|
@@ -9,6 +9,7 @@ Project-URL: Source code, https://github.com/tom-bjorkholm/excel-list-transform
|
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.13
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.14
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
12
13
|
Classifier: Operating System :: OS Independent
|
|
13
14
|
Classifier: Intended Audience :: Other Audience
|
|
14
15
|
Classifier: Topic :: Office/Business
|
|
@@ -16,13 +17,18 @@ Classifier: Typing :: Typed
|
|
|
16
17
|
Requires-Python: >=3.13
|
|
17
18
|
Description-Content-Type: text/markdown
|
|
18
19
|
License-File: LICENSE.txt
|
|
19
|
-
Requires-Dist: tableio-cfg-json>=0
|
|
20
|
-
Requires-Dist: tableio>=1.
|
|
21
|
-
Requires-Dist: config-as-json>=1.
|
|
22
|
-
Requires-Dist: versionreporter>=0.
|
|
23
|
-
Requires-Dist: argcomplete>=3.7.
|
|
20
|
+
Requires-Dist: tableio-cfg-json>=2.0
|
|
21
|
+
Requires-Dist: tableio>=1.3
|
|
22
|
+
Requires-Dist: config-as-json>=1.8
|
|
23
|
+
Requires-Dist: versionreporter>=0.5
|
|
24
|
+
Requires-Dist: argcomplete>=3.7.2
|
|
25
|
+
Requires-Dist: edit-cfg-json>=1.0.0
|
|
26
|
+
Requires-Dist: edit-cfg-json-tk>=1.0.0
|
|
27
|
+
Provides-Extra: textual
|
|
28
|
+
Requires-Dist: edit-cfg-json-textual>=1.0.0; extra == "textual"
|
|
24
29
|
Dynamic: author
|
|
25
30
|
Dynamic: license-file
|
|
31
|
+
Dynamic: provides-extra
|
|
26
32
|
Dynamic: requires-dist
|
|
27
33
|
Dynamic: requires-python
|
|
28
34
|
|
|
@@ -63,7 +69,8 @@ This small python application:
|
|
|
63
69
|
|
|
64
70
|
How this is done is governed by a configuration file. The application can
|
|
65
71
|
create a number of example configuration files with accompanying description
|
|
66
|
-
text files
|
|
72
|
+
text files, and can open a configuration file in a configuration editor that
|
|
73
|
+
explains every setting.
|
|
67
74
|
|
|
68
75
|
## Installing it
|
|
69
76
|
|
|
@@ -84,6 +91,19 @@ pip3 install --upgrade excel-list-transform
|
|
|
84
91
|
pip install --upgrade excel-list-transform
|
|
85
92
|
````
|
|
86
93
|
|
|
94
|
+
### Installing the terminal configuration editor (optional)
|
|
95
|
+
|
|
96
|
+
The "editcfg" sub-command opens the configuration editor in a window when
|
|
97
|
+
there is a display. To also be able to edit in the terminal (for instance
|
|
98
|
+
over a remote shell without a display), install the optional extra
|
|
99
|
+
"textual":
|
|
100
|
+
|
|
101
|
+
````sh
|
|
102
|
+
pip3 install --upgrade "excel-list-transform[textual]"
|
|
103
|
+
````
|
|
104
|
+
|
|
105
|
+
(On Microsoft Windows use `pip` instead of `pip3`.)
|
|
106
|
+
|
|
87
107
|
## Running the application
|
|
88
108
|
|
|
89
109
|
### Running the application on mac and Linux
|
|
@@ -97,6 +117,8 @@ python3 -m excel_list_transform cfg-example -k forms_to_rrs -r by_name -o exampl
|
|
|
97
117
|
python3 -m excel_list_transform transform -c example.cfg -i input.xlsx -o output.xlsx
|
|
98
118
|
python3 -m excel_list_transform migrate-cfg --help
|
|
99
119
|
python3 -m excel_list_transform migrate-cfg -i old.cfg -o new.cfg
|
|
120
|
+
python3 -m excel_list_transform editcfg --help
|
|
121
|
+
python3 -m excel_list_transform editcfg -i example.cfg
|
|
100
122
|
````
|
|
101
123
|
|
|
102
124
|
### Running the application on Microsoft Windows
|
|
@@ -110,6 +132,8 @@ python -m excel_list_transform cfg-example -k forms_to_rrs -r by_name -o example
|
|
|
110
132
|
python -m excel_list_transform transform -c example.cfg -i input.xlsx -o output.xlsx
|
|
111
133
|
python -m excel_list_transform migrate-cfg --help
|
|
112
134
|
python -m excel_list_transform migrate-cfg -i old.cfg -o new.cfg
|
|
135
|
+
python -m excel_list_transform editcfg --help
|
|
136
|
+
python -m excel_list_transform editcfg -i example.cfg
|
|
113
137
|
````
|
|
114
138
|
|
|
115
139
|
## Suggested way to get started
|
|
@@ -120,6 +144,8 @@ python -m excel_list_transform migrate-cfg -i old.cfg -o new.cfg
|
|
|
120
144
|
description (.txt) files.
|
|
121
145
|
3. Find an example that is close to what you want to achieve.
|
|
122
146
|
4. Modify that configuration file to achieve what you want to achieve.
|
|
147
|
+
Use the "editcfg" sub-command to modify it in a configuration editor that
|
|
148
|
+
explains every setting (or modify it in a text editor).
|
|
123
149
|
5. Use the "transform" sub-command to read your data and output it transformed
|
|
124
150
|
or reorganized according to your modified configuration file.
|
|
125
151
|
6. Read the produced output. If necessary go back to step 4 and adjust how the
|
|
@@ -139,6 +165,23 @@ text file describing it.
|
|
|
139
165
|
Read the text file describing the configuration file while looking at the
|
|
140
166
|
configuration file to understand the syntax and the possible options.
|
|
141
167
|
|
|
168
|
+
### Editing a configuration file
|
|
169
|
+
|
|
170
|
+
The "editcfg" sub-command opens a configuration file in a configuration
|
|
171
|
+
editor. The editor shows an explanation of every setting, checks the values
|
|
172
|
+
before saving, and keeps a backup (.bak) of the file it overwrites. It opens
|
|
173
|
+
in a window when there is a display, otherwise in the terminal (if the
|
|
174
|
+
optional extra "textual" is installed, see above). Use the "--ui" option to
|
|
175
|
+
choose the editor yourself, and the "-o" option to save to another file than
|
|
176
|
+
the one you opened.
|
|
177
|
+
|
|
178
|
+
"column_ref" cannot be changed in the editor, as the rest of the file is
|
|
179
|
+
written for it. Generate a new example with the other "-r" value instead.
|
|
180
|
+
|
|
181
|
+
There is a separate user guide for the editor opened by the "editcfg"
|
|
182
|
+
sub-command. See
|
|
183
|
+
[https://github.com/tom-bjorkholm/edit-cfg-json/blob/master/doc/end_users_guide.md](https://github.com/tom-bjorkholm/edit-cfg-json/blob/master/doc/end_users_guide.md)
|
|
184
|
+
|
|
142
185
|
## Performance
|
|
143
186
|
|
|
144
187
|
This application is written for the moderate amounts of data when
|
|
@@ -270,7 +313,8 @@ referenced by number.
|
|
|
270
313
|
The first operation is to split rows based on column values.
|
|
271
314
|
This operation is configured using the **"s01_split_rows"** record,
|
|
272
315
|
that has an array of splits to be done. Each row split has the
|
|
273
|
-
following keys: **"column"**, **"separators"
|
|
316
|
+
following keys: **"column"**, **"separators"**, **"not_separators"**
|
|
317
|
+
and **"empty_parts"**.
|
|
274
318
|
|
|
275
319
|
The **"column"** keyword is used to identify the column that is
|
|
276
320
|
split into several rows. This is a column number in the case of
|
|
@@ -286,11 +330,36 @@ these strings are present in the identified column it is seen
|
|
|
286
330
|
as the separator between the parts of the column value that go
|
|
287
331
|
into different rows.
|
|
288
332
|
|
|
333
|
+
Separators must not be empty strings. If more than one
|
|
334
|
+
separator matches at the same position, the longest one is used.
|
|
335
|
+
|
|
289
336
|
**"not_separators"** take as argument a list of strings. These strings
|
|
290
337
|
are not regarded as separators even if they include the strings
|
|
291
338
|
of one or more separator. (For instance ";" could be a separator,
|
|
292
339
|
but using **"not_separators"** the string "\\;" could be seen as not
|
|
293
340
|
a separator.)
|
|
341
|
+
The column value is scanned from the start. At each position a
|
|
342
|
+
not-separator takes precedence over a separator, so a separator
|
|
343
|
+
that is part of a not-separator never splits the value.
|
|
344
|
+
|
|
345
|
+
**"empty_parts"** decides what happens to empty parts. A part is the
|
|
346
|
+
text between two separators, or between a separator and the start
|
|
347
|
+
or end of the value. A part is empty if it is "" or only whitespace.
|
|
348
|
+
Empty parts come from a separator at the start or end of the value,
|
|
349
|
+
or from two adjacent separators. **"empty_parts"** can have the values:
|
|
350
|
+
|
|
351
|
+
- *"KEEP_ALL"*: keep all empty parts. They give rows where the column
|
|
352
|
+
is empty. "a,,b," split at "," gives "a", "", "b" and "".
|
|
353
|
+
- *"DROP_ALL"*: drop all empty parts. "a,,b," gives "a" and "b".
|
|
354
|
+
- *"DROP_TRAILING"*: drop only the empty parts at the end. "a,,b,"
|
|
355
|
+
gives "a", "" and "b", and "a,b,," gives "a" and "b". This is
|
|
356
|
+
useful when a separator is written after every element of a list,
|
|
357
|
+
also after the last one.
|
|
358
|
+
|
|
359
|
+
If all parts are dropped (for instance the value "," with *"DROP_ALL"*),
|
|
360
|
+
the row is kept once with the value "" in the column. An empty cell
|
|
361
|
+
is not split. Configuration files without **"empty_parts"** (from older
|
|
362
|
+
versions) get *"KEEP_ALL"*, which is how older versions worked.
|
|
294
363
|
|
|
295
364
|
### "s02_merge_rows"
|
|
296
365
|
|
|
@@ -309,6 +378,7 @@ For each column that has the same value for all rows merged, that
|
|
|
309
378
|
value will be in the merged row. When rows being merged have different
|
|
310
379
|
values for a column, the set of unique values from different rows
|
|
311
380
|
will form the value for that column in the merged row.
|
|
381
|
+
Empty values are left out.
|
|
312
382
|
|
|
313
383
|
The **"separator"** keyword is used to specify the string that is
|
|
314
384
|
concatenated between values for one column from different rows
|
|
@@ -346,10 +416,10 @@ the least confusion is to split columns to the right before
|
|
|
346
416
|
columns to the left. Named references also helps to avoid
|
|
347
417
|
confusion.)
|
|
348
418
|
|
|
349
|
-
Each split has the following keys: **"column"**, **"separator"
|
|
350
|
-
**"where"**. In the case of number column
|
|
351
|
-
also the key **"store_single"**. In the case of
|
|
352
|
-
there is instead the key **"right_name"**.
|
|
419
|
+
Each split has the following keys: **"column"**, **"separator"**,
|
|
420
|
+
**"where"** and **"end_separators"**. In the case of number column
|
|
421
|
+
references there is also the key **"store_single"**. In the case of
|
|
422
|
+
named column references there is instead the key **"right_name"**.
|
|
353
423
|
|
|
354
424
|
**"column"** takes as argument the column to be split. This is a
|
|
355
425
|
column number in the case of *"BY_NUMBER"*, and a column name/title
|
|
@@ -358,6 +428,7 @@ in the case of *"BY_NAME"*.
|
|
|
358
428
|
**"separator"** is a string of characters that indicate the position
|
|
359
429
|
where the column shall be split. (For instance a single space
|
|
360
430
|
if splitting between two words.)
|
|
431
|
+
The separator must not be an empty string.
|
|
361
432
|
|
|
362
433
|
**"where"** can either have the value *"RIGHTMOST"* or the value
|
|
363
434
|
*"LEFTMOST"*. This is used if the separator string is present
|
|
@@ -365,6 +436,25 @@ more than once in the column value to split. The split is then
|
|
|
365
436
|
done at the leftmost or rightmost occurrence according to the
|
|
366
437
|
value of **"where"**.
|
|
367
438
|
|
|
439
|
+
**"end_separators"** decides what happens to separators at the start
|
|
440
|
+
or end of the value, before the split is done. Without removing them,
|
|
441
|
+
"a,b," split at the rightmost "," gives "a,b" and "", and split at
|
|
442
|
+
the leftmost "," gives "a" and "b,". **"end_separators"** can have the
|
|
443
|
+
values:
|
|
444
|
+
|
|
445
|
+
- *"KEEP"*: keep the value as it is.
|
|
446
|
+
- *"STRIP_LEADING"*: remove separators at the start of the value.
|
|
447
|
+
- *"STRIP_TRAILING"*: remove separators at the end of the value.
|
|
448
|
+
- *"STRIP_BOTH_ENDS"*: remove separators at both the start and the end
|
|
449
|
+
of the value.
|
|
450
|
+
|
|
451
|
+
All consecutive separators at a stripped end are removed, together
|
|
452
|
+
with any whitespace between them. For instance "a,b, ," with
|
|
453
|
+
*"STRIP_TRAILING"* becomes "a,b" before it is split. A value that
|
|
454
|
+
consists only of separators and whitespace becomes "".
|
|
455
|
+
Configuration files without **"end_separators"** (from older versions)
|
|
456
|
+
get *"KEEP"*, which is how older versions worked.
|
|
457
|
+
|
|
368
458
|
**"right_name"** is only used if column references are *"BY_NAME"*.
|
|
369
459
|
After the split the left column uses the original column name,
|
|
370
460
|
and **"right_name"** is used as the name of the new right column.
|
|
@@ -395,6 +485,7 @@ column references are column numbers.
|
|
|
395
485
|
|
|
396
486
|
**"separator"** is a string of characters that is inserted between
|
|
397
487
|
the column values being merged.
|
|
488
|
+
Empty values are left out.
|
|
398
489
|
|
|
399
490
|
### "s06_place_columns_first"
|
|
400
491
|
|
|
@@ -414,6 +505,8 @@ column number in the case of *"BY_NUMBER"*, and a column name/title
|
|
|
414
505
|
in the case of *"BY_NAME"*.
|
|
415
506
|
|
|
416
507
|
**"name"** is the new name/title of the column identified by **"column"**.
|
|
508
|
+
In the case of *"BY_NAME"* the renames are done in the listed order,
|
|
509
|
+
and a rename must not give a column the name of an existing column.
|
|
417
510
|
|
|
418
511
|
### "s08_insert_columns"
|
|
419
512
|
|
|
@@ -486,6 +579,8 @@ The value of the **"s10_column_order"** key is a list of column names.
|
|
|
486
579
|
The columns will be output in this order.
|
|
487
580
|
Columns not mentioned in **"s10_column_order"** will not be output,
|
|
488
581
|
and will thus be removed.
|
|
582
|
+
Each name in **"s10_column_order"** must be the name of an existing
|
|
583
|
+
column (as named after all other steps).
|
|
489
584
|
(For *"BY_NUMBER"* see **"s04_remove_columns"** and **"s06_place_columns_first"**.)
|
|
490
585
|
|
|
491
586
|
## Utility for recoding text files
|
|
@@ -510,9 +605,10 @@ Source code and tests are available at [https://github.com/tom-bjorkholm/excel-l
|
|
|
510
605
|
|
|
511
606
|
## Test summary
|
|
512
607
|
|
|
513
|
-
- Test result:
|
|
608
|
+
- Test result: 1693 passed in 88s (0:01:28)
|
|
514
609
|
- No flake8 warnings.
|
|
515
610
|
- No mypy errors found.
|
|
611
|
+
- No pylint warnings.
|
|
516
612
|
- No python layout warnings.
|
|
517
|
-
- Built version(s): 1.
|
|
518
|
-
- Build and test using Python 3.
|
|
613
|
+
- Built version(s): 1.3
|
|
614
|
+
- Build and test using Python 3.15.2
|
|
@@ -45,7 +45,10 @@ This small python application:
|
|
|
45
45
|
an ODS spreadsheet file, a comma separated values (CSV) file, or
|
|
46
46
|
any of a number of other file formats.
|
|
47
47
|
|
|
48
|
-
How this is done is governed by a configuration file. The application can
|
|
48
|
+
How this is done is governed by a configuration file. The application can
|
|
49
|
+
create a number of example configuration files with accompanying description
|
|
50
|
+
text files, and can open a configuration file in a configuration editor
|
|
51
|
+
that explains every setting.
|
|
49
52
|
|
|
50
53
|
## Cloning
|
|
51
54
|
|
|
@@ -107,9 +110,10 @@ the built and installed application in the virtual environment `./venv`.
|
|
|
107
110
|
|
|
108
111
|
## Test summary
|
|
109
112
|
|
|
110
|
-
- Test result:
|
|
113
|
+
- Test result: 1693 passed in 88s (0:01:28)
|
|
111
114
|
- No flake8 warnings.
|
|
112
115
|
- No mypy errors found.
|
|
116
|
+
- No pylint warnings.
|
|
113
117
|
- No python layout warnings.
|
|
114
|
-
- Built version(s): 1.
|
|
115
|
-
- Build and test using Python 3.
|
|
118
|
+
- Built version(s): 1.3
|
|
119
|
+
- Build and test using Python 3.15.2
|
|
@@ -1,31 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: excel-list-transform
|
|
3
|
-
Version: 1.1
|
|
4
|
-
Summary: Transform table data with configurable row and column changes.
|
|
5
|
-
Author: Tom Björkholm
|
|
6
|
-
Author-email: Tom Björkholm <klausuler_linnet0q@icloud.com>
|
|
7
|
-
License-Expression: MIT
|
|
8
|
-
Project-URL: Source code, https://github.com/tom-bjorkholm/excel-list-transform
|
|
9
|
-
Classifier: Programming Language :: Python :: 3
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.14
|
|
12
|
-
Classifier: Operating System :: OS Independent
|
|
13
|
-
Classifier: Intended Audience :: Other Audience
|
|
14
|
-
Classifier: Topic :: Office/Business
|
|
15
|
-
Classifier: Typing :: Typed
|
|
16
|
-
Requires-Python: >=3.13
|
|
17
|
-
Description-Content-Type: text/markdown
|
|
18
|
-
License-File: LICENSE.txt
|
|
19
|
-
Requires-Dist: tableio-cfg-json>=0.8
|
|
20
|
-
Requires-Dist: tableio>=1.1
|
|
21
|
-
Requires-Dist: config-as-json>=1.4
|
|
22
|
-
Requires-Dist: versionreporter>=0.4
|
|
23
|
-
Requires-Dist: argcomplete>=3.7.0
|
|
24
|
-
Dynamic: author
|
|
25
|
-
Dynamic: license-file
|
|
26
|
-
Dynamic: requires-dist
|
|
27
|
-
Dynamic: requires-python
|
|
28
|
-
|
|
29
1
|
# excel-list-transform
|
|
30
2
|
|
|
31
3
|
## Background
|
|
@@ -63,7 +35,8 @@ This small python application:
|
|
|
63
35
|
|
|
64
36
|
How this is done is governed by a configuration file. The application can
|
|
65
37
|
create a number of example configuration files with accompanying description
|
|
66
|
-
text files
|
|
38
|
+
text files, and can open a configuration file in a configuration editor that
|
|
39
|
+
explains every setting.
|
|
67
40
|
|
|
68
41
|
## Installing it
|
|
69
42
|
|
|
@@ -84,6 +57,19 @@ pip3 install --upgrade excel-list-transform
|
|
|
84
57
|
pip install --upgrade excel-list-transform
|
|
85
58
|
````
|
|
86
59
|
|
|
60
|
+
### Installing the terminal configuration editor (optional)
|
|
61
|
+
|
|
62
|
+
The "editcfg" sub-command opens the configuration editor in a window when
|
|
63
|
+
there is a display. To also be able to edit in the terminal (for instance
|
|
64
|
+
over a remote shell without a display), install the optional extra
|
|
65
|
+
"textual":
|
|
66
|
+
|
|
67
|
+
````sh
|
|
68
|
+
pip3 install --upgrade "excel-list-transform[textual]"
|
|
69
|
+
````
|
|
70
|
+
|
|
71
|
+
(On Microsoft Windows use `pip` instead of `pip3`.)
|
|
72
|
+
|
|
87
73
|
## Running the application
|
|
88
74
|
|
|
89
75
|
### Running the application on mac and Linux
|
|
@@ -97,6 +83,8 @@ python3 -m excel_list_transform cfg-example -k forms_to_rrs -r by_name -o exampl
|
|
|
97
83
|
python3 -m excel_list_transform transform -c example.cfg -i input.xlsx -o output.xlsx
|
|
98
84
|
python3 -m excel_list_transform migrate-cfg --help
|
|
99
85
|
python3 -m excel_list_transform migrate-cfg -i old.cfg -o new.cfg
|
|
86
|
+
python3 -m excel_list_transform editcfg --help
|
|
87
|
+
python3 -m excel_list_transform editcfg -i example.cfg
|
|
100
88
|
````
|
|
101
89
|
|
|
102
90
|
### Running the application on Microsoft Windows
|
|
@@ -110,6 +98,8 @@ python -m excel_list_transform cfg-example -k forms_to_rrs -r by_name -o example
|
|
|
110
98
|
python -m excel_list_transform transform -c example.cfg -i input.xlsx -o output.xlsx
|
|
111
99
|
python -m excel_list_transform migrate-cfg --help
|
|
112
100
|
python -m excel_list_transform migrate-cfg -i old.cfg -o new.cfg
|
|
101
|
+
python -m excel_list_transform editcfg --help
|
|
102
|
+
python -m excel_list_transform editcfg -i example.cfg
|
|
113
103
|
````
|
|
114
104
|
|
|
115
105
|
## Suggested way to get started
|
|
@@ -120,6 +110,8 @@ python -m excel_list_transform migrate-cfg -i old.cfg -o new.cfg
|
|
|
120
110
|
description (.txt) files.
|
|
121
111
|
3. Find an example that is close to what you want to achieve.
|
|
122
112
|
4. Modify that configuration file to achieve what you want to achieve.
|
|
113
|
+
Use the "editcfg" sub-command to modify it in a configuration editor that
|
|
114
|
+
explains every setting (or modify it in a text editor).
|
|
123
115
|
5. Use the "transform" sub-command to read your data and output it transformed
|
|
124
116
|
or reorganized according to your modified configuration file.
|
|
125
117
|
6. Read the produced output. If necessary go back to step 4 and adjust how the
|
|
@@ -139,6 +131,23 @@ text file describing it.
|
|
|
139
131
|
Read the text file describing the configuration file while looking at the
|
|
140
132
|
configuration file to understand the syntax and the possible options.
|
|
141
133
|
|
|
134
|
+
### Editing a configuration file
|
|
135
|
+
|
|
136
|
+
The "editcfg" sub-command opens a configuration file in a configuration
|
|
137
|
+
editor. The editor shows an explanation of every setting, checks the values
|
|
138
|
+
before saving, and keeps a backup (.bak) of the file it overwrites. It opens
|
|
139
|
+
in a window when there is a display, otherwise in the terminal (if the
|
|
140
|
+
optional extra "textual" is installed, see above). Use the "--ui" option to
|
|
141
|
+
choose the editor yourself, and the "-o" option to save to another file than
|
|
142
|
+
the one you opened.
|
|
143
|
+
|
|
144
|
+
"column_ref" cannot be changed in the editor, as the rest of the file is
|
|
145
|
+
written for it. Generate a new example with the other "-r" value instead.
|
|
146
|
+
|
|
147
|
+
There is a separate user guide for the editor opened by the "editcfg"
|
|
148
|
+
sub-command. See
|
|
149
|
+
[https://github.com/tom-bjorkholm/edit-cfg-json/blob/master/doc/end_users_guide.md](https://github.com/tom-bjorkholm/edit-cfg-json/blob/master/doc/end_users_guide.md)
|
|
150
|
+
|
|
142
151
|
## Performance
|
|
143
152
|
|
|
144
153
|
This application is written for the moderate amounts of data when
|
|
@@ -270,7 +279,8 @@ referenced by number.
|
|
|
270
279
|
The first operation is to split rows based on column values.
|
|
271
280
|
This operation is configured using the **"s01_split_rows"** record,
|
|
272
281
|
that has an array of splits to be done. Each row split has the
|
|
273
|
-
following keys: **"column"**, **"separators"
|
|
282
|
+
following keys: **"column"**, **"separators"**, **"not_separators"**
|
|
283
|
+
and **"empty_parts"**.
|
|
274
284
|
|
|
275
285
|
The **"column"** keyword is used to identify the column that is
|
|
276
286
|
split into several rows. This is a column number in the case of
|
|
@@ -286,11 +296,36 @@ these strings are present in the identified column it is seen
|
|
|
286
296
|
as the separator between the parts of the column value that go
|
|
287
297
|
into different rows.
|
|
288
298
|
|
|
299
|
+
Separators must not be empty strings. If more than one
|
|
300
|
+
separator matches at the same position, the longest one is used.
|
|
301
|
+
|
|
289
302
|
**"not_separators"** take as argument a list of strings. These strings
|
|
290
303
|
are not regarded as separators even if they include the strings
|
|
291
304
|
of one or more separator. (For instance ";" could be a separator,
|
|
292
305
|
but using **"not_separators"** the string "\\;" could be seen as not
|
|
293
306
|
a separator.)
|
|
307
|
+
The column value is scanned from the start. At each position a
|
|
308
|
+
not-separator takes precedence over a separator, so a separator
|
|
309
|
+
that is part of a not-separator never splits the value.
|
|
310
|
+
|
|
311
|
+
**"empty_parts"** decides what happens to empty parts. A part is the
|
|
312
|
+
text between two separators, or between a separator and the start
|
|
313
|
+
or end of the value. A part is empty if it is "" or only whitespace.
|
|
314
|
+
Empty parts come from a separator at the start or end of the value,
|
|
315
|
+
or from two adjacent separators. **"empty_parts"** can have the values:
|
|
316
|
+
|
|
317
|
+
- *"KEEP_ALL"*: keep all empty parts. They give rows where the column
|
|
318
|
+
is empty. "a,,b," split at "," gives "a", "", "b" and "".
|
|
319
|
+
- *"DROP_ALL"*: drop all empty parts. "a,,b," gives "a" and "b".
|
|
320
|
+
- *"DROP_TRAILING"*: drop only the empty parts at the end. "a,,b,"
|
|
321
|
+
gives "a", "" and "b", and "a,b,," gives "a" and "b". This is
|
|
322
|
+
useful when a separator is written after every element of a list,
|
|
323
|
+
also after the last one.
|
|
324
|
+
|
|
325
|
+
If all parts are dropped (for instance the value "," with *"DROP_ALL"*),
|
|
326
|
+
the row is kept once with the value "" in the column. An empty cell
|
|
327
|
+
is not split. Configuration files without **"empty_parts"** (from older
|
|
328
|
+
versions) get *"KEEP_ALL"*, which is how older versions worked.
|
|
294
329
|
|
|
295
330
|
### "s02_merge_rows"
|
|
296
331
|
|
|
@@ -309,6 +344,7 @@ For each column that has the same value for all rows merged, that
|
|
|
309
344
|
value will be in the merged row. When rows being merged have different
|
|
310
345
|
values for a column, the set of unique values from different rows
|
|
311
346
|
will form the value for that column in the merged row.
|
|
347
|
+
Empty values are left out.
|
|
312
348
|
|
|
313
349
|
The **"separator"** keyword is used to specify the string that is
|
|
314
350
|
concatenated between values for one column from different rows
|
|
@@ -346,10 +382,10 @@ the least confusion is to split columns to the right before
|
|
|
346
382
|
columns to the left. Named references also helps to avoid
|
|
347
383
|
confusion.)
|
|
348
384
|
|
|
349
|
-
Each split has the following keys: **"column"**, **"separator"
|
|
350
|
-
**"where"**. In the case of number column
|
|
351
|
-
also the key **"store_single"**. In the case of
|
|
352
|
-
there is instead the key **"right_name"**.
|
|
385
|
+
Each split has the following keys: **"column"**, **"separator"**,
|
|
386
|
+
**"where"** and **"end_separators"**. In the case of number column
|
|
387
|
+
references there is also the key **"store_single"**. In the case of
|
|
388
|
+
named column references there is instead the key **"right_name"**.
|
|
353
389
|
|
|
354
390
|
**"column"** takes as argument the column to be split. This is a
|
|
355
391
|
column number in the case of *"BY_NUMBER"*, and a column name/title
|
|
@@ -358,6 +394,7 @@ in the case of *"BY_NAME"*.
|
|
|
358
394
|
**"separator"** is a string of characters that indicate the position
|
|
359
395
|
where the column shall be split. (For instance a single space
|
|
360
396
|
if splitting between two words.)
|
|
397
|
+
The separator must not be an empty string.
|
|
361
398
|
|
|
362
399
|
**"where"** can either have the value *"RIGHTMOST"* or the value
|
|
363
400
|
*"LEFTMOST"*. This is used if the separator string is present
|
|
@@ -365,6 +402,25 @@ more than once in the column value to split. The split is then
|
|
|
365
402
|
done at the leftmost or rightmost occurrence according to the
|
|
366
403
|
value of **"where"**.
|
|
367
404
|
|
|
405
|
+
**"end_separators"** decides what happens to separators at the start
|
|
406
|
+
or end of the value, before the split is done. Without removing them,
|
|
407
|
+
"a,b," split at the rightmost "," gives "a,b" and "", and split at
|
|
408
|
+
the leftmost "," gives "a" and "b,". **"end_separators"** can have the
|
|
409
|
+
values:
|
|
410
|
+
|
|
411
|
+
- *"KEEP"*: keep the value as it is.
|
|
412
|
+
- *"STRIP_LEADING"*: remove separators at the start of the value.
|
|
413
|
+
- *"STRIP_TRAILING"*: remove separators at the end of the value.
|
|
414
|
+
- *"STRIP_BOTH_ENDS"*: remove separators at both the start and the end
|
|
415
|
+
of the value.
|
|
416
|
+
|
|
417
|
+
All consecutive separators at a stripped end are removed, together
|
|
418
|
+
with any whitespace between them. For instance "a,b, ," with
|
|
419
|
+
*"STRIP_TRAILING"* becomes "a,b" before it is split. A value that
|
|
420
|
+
consists only of separators and whitespace becomes "".
|
|
421
|
+
Configuration files without **"end_separators"** (from older versions)
|
|
422
|
+
get *"KEEP"*, which is how older versions worked.
|
|
423
|
+
|
|
368
424
|
**"right_name"** is only used if column references are *"BY_NAME"*.
|
|
369
425
|
After the split the left column uses the original column name,
|
|
370
426
|
and **"right_name"** is used as the name of the new right column.
|
|
@@ -395,6 +451,7 @@ column references are column numbers.
|
|
|
395
451
|
|
|
396
452
|
**"separator"** is a string of characters that is inserted between
|
|
397
453
|
the column values being merged.
|
|
454
|
+
Empty values are left out.
|
|
398
455
|
|
|
399
456
|
### "s06_place_columns_first"
|
|
400
457
|
|
|
@@ -414,6 +471,8 @@ column number in the case of *"BY_NUMBER"*, and a column name/title
|
|
|
414
471
|
in the case of *"BY_NAME"*.
|
|
415
472
|
|
|
416
473
|
**"name"** is the new name/title of the column identified by **"column"**.
|
|
474
|
+
In the case of *"BY_NAME"* the renames are done in the listed order,
|
|
475
|
+
and a rename must not give a column the name of an existing column.
|
|
417
476
|
|
|
418
477
|
### "s08_insert_columns"
|
|
419
478
|
|
|
@@ -486,6 +545,8 @@ The value of the **"s10_column_order"** key is a list of column names.
|
|
|
486
545
|
The columns will be output in this order.
|
|
487
546
|
Columns not mentioned in **"s10_column_order"** will not be output,
|
|
488
547
|
and will thus be removed.
|
|
548
|
+
Each name in **"s10_column_order"** must be the name of an existing
|
|
549
|
+
column (as named after all other steps).
|
|
489
550
|
(For *"BY_NUMBER"* see **"s04_remove_columns"** and **"s06_place_columns_first"**.)
|
|
490
551
|
|
|
491
552
|
## Utility for recoding text files
|
|
@@ -510,9 +571,10 @@ Source code and tests are available at [https://github.com/tom-bjorkholm/excel-l
|
|
|
510
571
|
|
|
511
572
|
## Test summary
|
|
512
573
|
|
|
513
|
-
- Test result:
|
|
574
|
+
- Test result: 1693 passed in 88s (0:01:28)
|
|
514
575
|
- No flake8 warnings.
|
|
515
576
|
- No mypy errors found.
|
|
577
|
+
- No pylint warnings.
|
|
516
578
|
- No python layout warnings.
|
|
517
|
-
- Built version(s): 1.
|
|
518
|
-
- Build and test using Python 3.
|
|
579
|
+
- Built version(s): 1.3
|
|
580
|
+
- Build and test using Python 3.15.2
|