excel-list-transform 0.8.4__tar.gz → 0.9__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.
Files changed (58) hide show
  1. {excel_list_transform-0.8.4/excel_list_transform.egg-info → excel_list_transform-0.9}/PKG-INFO +160 -137
  2. excel_list_transform-0.9/README.md +116 -0
  3. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/README_pypi.md +148 -121
  4. {excel_list_transform-0.8.4 → excel_list_transform-0.9/excel_list_transform.egg-info}/PKG-INFO +160 -137
  5. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/excel_list_transform.egg-info/SOURCES.txt +3 -6
  6. excel_list_transform-0.9/excel_list_transform.egg-info/requires.txt +9 -0
  7. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/pyproject.toml +4 -4
  8. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/setup.py +11 -15
  9. excel_list_transform-0.9/src/excel_list_transform/__init__.py +3 -0
  10. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/__main__.py +2 -2
  11. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/check_indata_common.py +1 -1
  12. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/commontypes.py +3 -15
  13. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/config_enums.py +1 -16
  14. excel_list_transform-0.9/src/excel_list_transform/config_excel_list_transform.py +553 -0
  15. excel_list_transform-0.9/src/excel_list_transform/config_match.py +22 -0
  16. excel_list_transform-0.9/src/excel_list_transform/config_read_old.py +128 -0
  17. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/config_xls_list_transf_name.py +23 -19
  18. excel_list_transform-0.9/src/excel_list_transform/config_xls_list_transf_num.py +84 -0
  19. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/file_extension.py +1 -1
  20. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/file_must_exist.py +1 -1
  21. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/generate_cfg.py +117 -94
  22. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/generate_txt.py +142 -75
  23. excel_list_transform-0.9/src/excel_list_transform/handle_empty_column.py +17 -0
  24. excel_list_transform-0.9/src/excel_list_transform/handle_tableio.py +131 -0
  25. excel_list_transform-0.9/src/excel_list_transform/migrate_cfg.py +22 -0
  26. excel_list_transform-0.9/src/excel_list_transform/migrate_cfg_warn_hook.py +21 -0
  27. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/num_named_conversion.py +2 -25
  28. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/recode.py +4 -6
  29. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/rewrite_value.py +8 -10
  30. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/row_split_merge.py +16 -32
  31. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/str_to_enum.py +1 -1
  32. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/transform_cmd.py +33 -23
  33. excel_list_transform-0.9/src/excel_list_transform/transform_func.py +41 -0
  34. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/transform_func_common.py +13 -16
  35. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/transform_func_named.py +16 -34
  36. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/transform_func_num.py +15 -29
  37. excel_list_transform-0.9/src/excel_list_transform/version_information.py +32 -0
  38. excel_list_transform-0.8.4/README.md +0 -85
  39. excel_list_transform-0.8.4/excel_list_transform.egg-info/requires.txt +0 -13
  40. excel_list_transform-0.8.4/src/excel_list_transform/__init__.py +0 -3
  41. excel_list_transform-0.8.4/src/excel_list_transform/assert_dict_equal.py +0 -57
  42. excel_list_transform-0.8.4/src/excel_list_transform/config.py +0 -572
  43. excel_list_transform-0.8.4/src/excel_list_transform/config_auto_change_hook.py +0 -59
  44. excel_list_transform-0.8.4/src/excel_list_transform/config_excel_list_transform.py +0 -391
  45. excel_list_transform-0.8.4/src/excel_list_transform/config_factory.py +0 -101
  46. excel_list_transform-0.8.4/src/excel_list_transform/config_xls_list_transf_num.py +0 -77
  47. excel_list_transform-0.8.4/src/excel_list_transform/handle_csv.py +0 -76
  48. excel_list_transform-0.8.4/src/excel_list_transform/handle_empty_column.py +0 -28
  49. excel_list_transform-0.8.4/src/excel_list_transform/handle_excel.py +0 -234
  50. excel_list_transform-0.8.4/src/excel_list_transform/migrate_cfg.py +0 -33
  51. excel_list_transform-0.8.4/src/excel_list_transform/migrate_cfg_warn_hook.py +0 -32
  52. excel_list_transform-0.8.4/src/excel_list_transform/transform_func.py +0 -50
  53. excel_list_transform-0.8.4/src/excel_list_transform/version_information.py +0 -210
  54. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/LICENSE.txt +0 -0
  55. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/excel_list_transform.egg-info/dependency_links.txt +0 -0
  56. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/excel_list_transform.egg-info/top_level.txt +0 -0
  57. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/setup.cfg +0 -0
  58. {excel_list_transform-0.8.4 → excel_list_transform-0.9}/src/excel_list_transform/py.typed +0 -0
@@ -1,29 +1,25 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: excel-list-transform
3
- Version: 0.8.4
4
- Summary: Transform a list in excel or CSV
3
+ Version: 0.9
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>
7
+ License-Expression: MIT
7
8
  Project-URL: Source code, https://bitbucket.org/tom-bjorkholm/excel-list-transform
8
9
  Classifier: Programming Language :: Python :: 3
9
- Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
- Requires-Python: <3.13,>=3.12
11
+ Requires-Python: >=3.13
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE.txt
14
- Requires-Dist: openpyxl>=3.1.5
15
- Requires-Dist: types-openpyxl>=3.1.5.20250919
16
- Requires-Dist: pylightxl>=1.61
17
- Requires-Dist: XlsxWriter>=3.2.9
14
+ Requires-Dist: tableio-cfg-json>=0.3
15
+ Requires-Dist: tableio>=0.9
16
+ Requires-Dist: config-as-json>=1.1
17
+ Requires-Dist: versionreporter>=0.2
18
18
  Requires-Dist: argcomplete>=3.6.3
19
- Requires-Dist: pypi-simple>=1.8.0
20
- Requires-Dist: requests>=2.32.5
21
- Requires-Dist: types-requests>=2.32.4.20250913
22
- Requires-Dist: packaging>=25.0
23
- Requires-Dist: pip>=25.3
24
- Requires-Dist: setuptools>=80.9.0
25
- Requires-Dist: build>=1.3.0
26
- Requires-Dist: wheel>=0.45.1
19
+ Requires-Dist: pip>=26.1
20
+ Requires-Dist: setuptools>=82.0.1
21
+ Requires-Dist: build>=1.5.0
22
+ Requires-Dist: wheel>=0.47.0
27
23
  Dynamic: author
28
24
  Dynamic: license-file
29
25
  Dynamic: requires-dist
@@ -33,30 +29,47 @@ Dynamic: requires-python
33
29
 
34
30
  ## Background
35
31
 
36
- This python application was born out of an experience at sail racing events. At the start of the events we received an excel list with participants (from a registration web) to enter into the scoring software and into tool for online notice board. The information was present in the excel file, but the columns were all wrong. To avoid the stressful manual rework of the information in the excel list this application was created.
32
+ This python application was born out of an experience at sail racing events.
33
+ At the start of the events we received an excel list with participants (from
34
+ a registration web) to enter into the scoring software and into tool for
35
+ online notice board. The information was present in the excel file, but the
36
+ columns were all wrong. To avoid the stressful manual rework of the
37
+ information in the excel list this application was created.
37
38
 
38
39
  ## What it does
39
40
 
40
41
  This small python application:
41
42
 
42
- * reads data (that is a list with columns) from an excel file or from a comma separate values (CSV) file.
43
- * split rows in the list (creating separate rows when a cell contains something that can be split to several values, see below)
44
- * merge rows (if specified columns have the same value in several rows the rows are merged to one row)
45
- * splits columns in the list (like creating "first name" and "last name" columns from "name" column)
46
- * merges columns in the list (like creating "name" column from "first name" and "last name" columns)
47
- * removes columns in the list
48
- * reorders columns in the list
49
- * renames columns in the list
50
- * inserts columns in the list
51
- * rewrites columns in the list (like transforming telephone numbers from local/national format to international format)
52
- * writes the resulting data (that is a list with columns) to an excel file or to a comma separate values (CSV) file.
53
-
54
- How this is done is governed by a configuration file. The application can create a number of example configuration files with accompanying description text files.
43
+ - reads data (that is a list with columns) from an excel file, an ODS file,
44
+ or from a comma separated values (CSV) file.
45
+ - split rows in the list (creating separate rows when a cell contains
46
+ something that can be split to several values, see below)
47
+ - merge rows (if specified columns have the same value in several rows
48
+ the rows are merged to one row)
49
+ - splits columns in the list (like creating "first name" and "last name"
50
+ columns from "name" column)
51
+ - merges columns in the list (like creating "name" column from "first name"
52
+ and "last name" columns)
53
+ - removes columns in the list
54
+ - reorders columns in the list
55
+ - renames columns in the list
56
+ - inserts columns in the list
57
+ - rewrites columns in the list (like transforming telephone numbers from
58
+ local/national format to international format)
59
+ - writes the resulting data (that is a list with columns) to an excel file,
60
+ an ODS spreadsheet file, a comma separated values (CSV) file, or
61
+ any of a number of other file formats.
62
+
63
+ How this is done is governed by a configuration file. The application can
64
+ create a number of example configuration files with accompanying description
65
+ text files.
55
66
 
56
67
  ## Installing it
57
68
 
58
- If you want to use it, install it using pip. A precondition is that you have Python installed on you computer. See version table below for information on needed Python version.
59
- Python can be downloaded from [https://www.python.org/downloads/](https://www.python.org/downloads/).
69
+ If you want to use it, install it using pip. A precondition is that you have
70
+ Python installed on your computer. See version table below for information
71
+ on needed Python version. Python can be downloaded
72
+ from [https://www.python.org/downloads/](https://www.python.org/downloads/).
60
73
 
61
74
  ### Installing on mac and Linux
62
75
 
@@ -94,6 +107,7 @@ pip install --upgrade excel-list-transform
94
107
  | 0.8.3 | 23 Jul 2025 | 3.13 or newer | Add split-row and merge-row |
95
108
  | 0.8.4 | 23 Nov 2025 | 3.12.x | Backport 0.8.5 to Python 3.12 |
96
109
  | 0.8.5 | 23 Nov 2025 | 3.13 or newer | Adapted to Python 3.14 |
110
+ | 0.9 | 06 Jun 2026 | 3.13 or newer | Many new input/output formats |
97
111
 
98
112
  ## Running the application
99
113
 
@@ -125,43 +139,62 @@ python -m excel_list_transform migrate-cfg -i old.cfg -o new.cfg
125
139
 
126
140
  ## Suggested way to get started
127
141
 
128
- 1. Use the "cfg-example" sub-command to generate a few example configuration (.cfg) files with description (.txt) files.
129
- 2. Read the example configuration (.cfg) files and the accompanying description (.txt) files.
142
+ 1. Use the "cfg-example" sub-command to generate a few example configuration
143
+ (.cfg) files with description (.txt) files.
144
+ 2. Read the example configuration (.cfg) files and the accompanying
145
+ description (.txt) files.
130
146
  3. Find an example that is close to what you want to achieve.
131
147
  4. Modify that configuration file to achieve what you want to achieve.
132
- 5. Use the "transform" sub-command to read your data and output it transformed or reorganized according to your modified configuration file.
133
- 6. Read the produced output. If necessary go back to step 4 and adjust how the data is transformed.
148
+ 5. Use the "transform" sub-command to read your data and output it transformed
149
+ or reorganized according to your modified configuration file.
150
+ 6. Read the produced output. If necessary go back to step 4 and adjust how the
151
+ data is transformed.
134
152
 
135
153
  ### Example configuration files
136
154
 
137
- When using the "cfg-example" sub-command to generate an example configuration file (say example.cfg) a text file describing the configuration and the syntax of the configuration file is also generated. If the example configuration file is named example.cfg, then the text file descriging the configuration is named example.txt.
155
+ When using the "cfg-example" sub-command to generate an example configuration
156
+ file (say example.cfg) a text file describing the configuration and the syntax
157
+ of the configuration file is also generated. If the example configuration
158
+ file is named example.cfg, then the text file describing the configuration
159
+ is named example.txt.
138
160
 
139
- You can generate several example configuration files each with an accompanying text file descriping it.
161
+ You can generate several example configuration files each with an accompanying
162
+ text file describing it.
140
163
 
141
- Read the text file describing the configuration file while looking at the configuration file to understand the syntax and the possible options.
164
+ Read the text file describing the configuration file while looking at the
165
+ configuration file to understand the syntax and the possible options.
142
166
 
143
167
  ## Performance
144
168
 
145
- This application is written for the moderate amounts of data when registering participants for the majority of sports events. If you have millions of rows this application is not for you.
169
+ This application is written for the moderate amounts of data when
170
+ registering participants for the majority of sports events. If you have
171
+ millions of rows this application is not for you.
172
+
173
+ With an input file consisting of 20 columns producing an output file of
174
+ 11 columns I have measured the following performance:
146
175
 
147
- With an input file consisting of 20 columns producing an output file of 11 columns I have measured the following performance on a MacBook Air (laptop) from 2020:
176
+ | number of rows | on MacBook Air M4 | on MacMini M4 Pro |
177
+ |----------------|-----------------------|-----------------------|
178
+ | 100 | less than 0.2 seconds | less than 0.2 seconds |
179
+ | 500 | | less than 2 seconds |
148
180
 
149
- * 1 000 rows processed in less than 0.5 seconds
150
- * 10 000 rows processed in less than 4 seconds
151
- * 80 000 rows processed in less than 30 seconds
152
- * 120 000 rows processed in 40 seconds
181
+ (A performance related fix in a library this application depends on is
182
+ expected soon.)
153
183
 
154
- Naturally your performance will be different based on computer hardware, operating system and Python version. Generally it should be reasonably fast for less than 10 000 rows, painfully slow but somewhat usable up to 100 000 rows and probably so slow that it is unusable for more than 100 000 rows.
184
+ Naturally your performance will be different based on computer
185
+ hardware, operating system and Python version.
155
186
 
156
187
  ## Description of how to write/change the configuration file
157
188
 
158
- The configuration file is in JSON syntax. [https://en.wikipedia.org/wiki/JSON](https://en.wikipedia.org/wiki/JSON)
189
+ The configuration file is in JSON syntax.
190
+ [https://en.wikipedia.org/wiki/JSON](https://en.wikipedia.org/wiki/JSON)
159
191
 
160
192
  The keywords and the nesting is important. The order of keywords
161
193
  have no significance (the examples use alphabetical order).
162
194
  Indentation and line breaks have no significance.
163
195
 
164
- The encoding for the configuration file must be UTF-8. (US-ACII is a subset of UTF-8.)
196
+ The encoding for the configuration file must be UTF-8. (US-ASCII is a
197
+ subset of UTF-8.)
165
198
 
166
199
  It is recommended that you let the command generate a configuration
167
200
  file and then edit that file to match your needs. It is NOT recommended
@@ -172,14 +205,15 @@ that the user writes the configuration file from scratch.
172
205
  The keyword **column_ref** is used to tell if the configuration
173
206
  references columns by name (value *"BY_NAME"*) or by number
174
207
  (value *"BY_NUMBER"*). The syntax of parts of the configuration file
175
- is slightly different depending on the how columns are referenced.
208
+ is slightly different depending on how columns are referenced.
176
209
  Thus, you first have to decide how you want to reference columns.
177
210
 
178
211
  Generally it is easier to write a correct configuration using *"BY_NAME"*,
179
- so *"BY_NAME"* is recommended when possible. *"BY_NAME"* imposes a few restrictions:
212
+ so *"BY_NAME"* is recommended when possible. *"BY_NAME"* imposes a few
213
+ restrictions:
180
214
 
181
- * each column need to have a unique text at the first line to use as column name.
182
- * the column names need to be stable and known.
215
+ - each column needs to have a unique text at the first line to use as column name.
216
+ - the column names need to be stable and known.
183
217
 
184
218
  If you cannot meet these restrictions you will have to reference the
185
219
  columns by number *"BY_NUMBER"*. When referencing the columns by number
@@ -191,49 +225,37 @@ right. The leftmost column is number 0.
191
225
 
192
226
  ## Type of input and output file
193
227
 
194
- The type of input file to read is determined by **"in_type"**.
195
- The type of output file to write is determined by **"out_type"**.
196
- **"in_type"** and **"out_type"** can have values *"CSV"* or *"EXCEL"*.
197
-
198
- Excel files can be read and written using three libraries.
199
- **"in_excel_library"** and **"out_excel_library"** can have values
200
- *"OPENPYXL"*, *"XLSXWRITER"* or *"PYLIGHTXL"*. These are different
201
- third party libraries that can read/write excel. My experience
202
- is that *"PYLIGHTXL"* most often is able to read and write excel
203
- files correctly. If you have trouble reading/writing your
204
- particular excel file, please try different combinations of
205
- these libraries. **"in_excel_library"** is always needed in
206
- the configuration file but is not used if the input is CSV.
207
- **"out_excel_library"** is always needed in the configuration file
208
- but is not used if the output is CSV.
209
-
210
- Currently *"PYLIGHTXL"* appears to be best to write files for
211
- Microsoft Excel to open without complaints. But *"OPENPYXL"*
212
- appears to be best to write files to be imported by
213
- [https://www.racingrulesofsailing.org](https://www.racingrulesofsailing.org).
214
- When newer versions arrive this might change...
215
-
216
- Comma separated values files (CSV files) may differ slightly
217
- depening on the programs used to read/write them and the locale
218
- used. **"in_csv_dialect"** and **"out_csv_dialect"** changes how CSV files
219
- are read and written. They are always needed in the configuration
220
- file, but are not used if the input and output are excel files.
221
-
222
- Comma separated values files might have different encoding for
223
- the text in the file. [https://en.wikipedia.org/wiki/Character_encoding](https://en.wikipedia.org/wiki/Character_encoding)
224
- This is specified with **"in_csv_encoding"** and **"out_csv_encoding"**.
225
- Unless you know that you need another encoding leave these as
226
- in the generated example configuration. (In version 0.5 these
227
- configuration parameters are missing. To be compatible with 0.5
228
- configuration files "in_csv_encoding" defaults to "utf_8_sig"
229
- and "out_csv_encoding" defaults to "utf-8" if missing in the
230
- configuration file.)
228
+ The type of input file to read is configured in the **"input_table"**
229
+ section. The type of output file to write is configured in the
230
+ **"output_table"** section. These sections use the TableIO JSON
231
+ configuration syntax.
232
+
233
+ The most important keyword in each table section is **"format_name"**.
234
+ Generated examples commonly use *"Excel"* or *"CSV"*, but TableIO may
235
+ support more formats. In most cases you should leave **"implementation"**
236
+ missing or set to *null*. Then TableIO chooses a suitable implementation.
237
+ If you know that you need a specific implementation, you can add it
238
+ manually.
239
+
240
+ CSV files may differ slightly depending on the programs used to read/write
241
+ them and the locale used. CSV-specific settings are configured in the
242
+ nested **"csv"** section inside **"input_table"** or **"output_table"**.
243
+ The **"character_encoding"** keyword in the table section controls the
244
+ text encoding.
245
+ [https://en.wikipedia.org/wiki/Character_encoding](https://en.wikipedia.org/wiki/Character_encoding)
246
+
247
+ Output tables can request extra presentation features. Set
248
+ **"output_borders"** to *true* to request table borders. Set
249
+ **"output_filtered_table"** to *true* to request a filtered table area.
250
+ These features are ignorable requests. TableIO will prefer an
251
+ implementation that can provide them, but the transform can still write
252
+ the output if the selected file format cannot represent them.
231
253
 
232
254
  ## Extra spaces in excel input files
233
255
 
234
256
  When viewing an excel file in excel it is very hard to notice if
235
- some string value in a cell has trailing white space. These trailing
236
- trailing spaces can make the further processing of a file difficult
257
+ some string value in a cell has trailing whitespace. These trailing
258
+ spaces can make the further processing of a file difficult
237
259
  as the strings in the file are not what you thought they are.
238
260
  (This especially is a problem if you have trailing spaces in a
239
261
  cell on the first line, and refer to columns by their names.)
@@ -243,7 +265,7 @@ to strip off leading and trailing whitespace from all columns
243
265
  values read from the first line of the excel input file.
244
266
  The configuration **"in_excel_values_strip"** can be set to true,
245
267
  to strip off leading and trailing whitespace from all columns
246
- values read from from the other lines (not the first line) of
268
+ values read from the other lines (not the first line) of
247
269
  the excel input file. (In version 0.6.2 and earlier these are
248
270
  missing. To be compatible with version 0.6.2 and earlier
249
271
  **"in_excel_col_name_strip"** and **"in_excel_values_strip"**
@@ -251,10 +273,10 @@ defaults to false if missing in the configuration file.)
251
273
 
252
274
  ## Column manipulation
253
275
 
254
- A number or records starting with "s" and a number describe
276
+ A number of records starting with "s" and a number describe
255
277
  column manipulation to be done. These manipulations are done
256
- in order of the number: s1_(something) before s2_(something),
257
- before s3_(something). As the "s" number records might add, remove
278
+ in order of the number: s01_(something) before s02_(something),
279
+ before s03_(something). As the "s" number records might add, remove
258
280
  or rename columns, it is important to keep track of the order that
259
281
  they are applied.
260
282
 
@@ -266,12 +288,12 @@ referenced by number.
266
288
 
267
289
  The first operation is to split rows based on column values.
268
290
  This operation is configured using the **"s01_split_rows"** record,
269
- that have an array of splits to be done. Each row split has the
291
+ that has an array of splits to be done. Each row split has the
270
292
  following keys: **"column"**, **"separators"** and **"not_separators"**.
271
293
 
272
294
  The **"column"** keyword is used to identify the column that is
273
295
  split into several rows. This is a column number in the case of
274
- *"BY_NUMBER"*, and a column name/title in the sace of *"BY_NAME"*.
296
+ *"BY_NUMBER"*, and a column name/title in the case of *"BY_NAME"*.
275
297
 
276
298
  New rows will be created so that the parts of the identified
277
299
  column will be put in that column only one part per row.
@@ -283,7 +305,7 @@ these strings are present in the identified column it is seen
283
305
  as the separator between the parts of the column value that go
284
306
  into different rows.
285
307
 
286
- **"not_separators"** take as arguement a list of strings. These strings
308
+ **"not_separators"** take as argument a list of strings. These strings
287
309
  are not regarded as separators even if they include the strings
288
310
  of one or more separator. (For instance ";" could be a separator,
289
311
  but using **"not_separators"** the string "\\;" could be seen as not
@@ -293,14 +315,14 @@ a separator.)
293
315
 
294
316
  The next operation is to merge rows based on column values.
295
317
  This is the opposite operation to the splitting of rows.
296
- Row mergins is configured using the **"s02_merge_rows"** record,
297
- that have an array of merges to be done. Each row merge have
318
+ Row merging is configured using the **"s02_merge_rows"** record,
319
+ that has an array of merges to be done. Each row merge has
298
320
  the following keys: **"columns"** and **"separator"**.
299
321
 
300
322
  The **"columns"** keyword is used to identify the columns that need
301
323
  to have identical values to merge two or more rows. The **"columns"**
302
- keyword take a list of columns. These are column numbers in the case of
303
- *"BY_NUMBER"*, and a column names/titles in the sace of *"BY_NAME"*.
324
+ keyword takes a list of columns. These are column numbers in the case of
325
+ *"BY_NUMBER"*, and column names/titles in the case of *"BY_NAME"*.
304
326
 
305
327
  For each column that has the same value for all rows merged, that
306
328
  value will be in the merged row. When rows being merged have different
@@ -320,7 +342,7 @@ for customers in the following format:
320
342
  | Brewery | Beer | Smith + Bush |
321
343
  | Dairy | Milk | Jones |
322
344
 
323
- But for distrubuting it to customers you would like to have the
345
+ But for distributing it to customers you would like to have the
324
346
  list in the following format:
325
347
 
326
348
  | To | What | From |
@@ -330,27 +352,27 @@ list in the following format:
330
352
  | Bush | Beer | Brewery |
331
353
 
332
354
  To do this transformation we use the **"s01_split_rows"** to split
333
- rows base on the "To" column using " + " as separator.
355
+ rows based on the "To" column using " + " as separator.
334
356
  Then we use **"s02_merge_rows"** to merge the rows that have
335
357
  identical values in the "To" column.
336
358
 
337
359
  ### "s03_split_columns"
338
360
 
339
- The first operation that is done is splitting of columns.
340
- The key **"s03_split_columns"** have an array of splits to be
361
+ The first column operation that is done is splitting of columns.
362
+ The key **"s03_split_columns"** has an array of splits to be
341
363
  done. (When the list of splits has more than one split,
342
364
  the least confusion is to split columns to the right before
343
365
  columns to the left. Named references also helps to avoid
344
366
  confusion.)
345
367
 
346
368
  Each split has the following keys: **"column"**, **"separator"** and
347
- **"where"**. In the case of number column references the there is
369
+ **"where"**. In the case of number column references there is
348
370
  also the key **"store_single"**. In the case of named column references
349
371
  there is instead the key **"right_name"**.
350
372
 
351
- **"column"** take as argument the column to be split. This is a
373
+ **"column"** takes as argument the column to be split. This is a
352
374
  column number in the case of *"BY_NUMBER"*, and a column name/title
353
- in the sace of *"BY_NAME"*.
375
+ in the case of *"BY_NAME"*.
354
376
 
355
377
  **"separator"** is a string of characters that indicate the position
356
378
  where the column shall be split. (For instance a single space
@@ -359,7 +381,7 @@ if splitting between two words.)
359
381
  **"where"** can either have the value *"RIGHTMOST"* or the value
360
382
  *"LEFTMOST"*. This is used if the separator string is present
361
383
  more than once in the column value to split. The split is then
362
- done at the leftmost or rightmost occurence according to the
384
+ done at the leftmost or rightmost occurrence according to the
363
385
  value of **"where"**.
364
386
 
365
387
  **"right_name"** is only used if column references are *"BY_NAME"*.
@@ -379,11 +401,11 @@ always stored in the column with the original name.
379
401
 
380
402
  **"s04_remove_columns"** is only used with column references *"BY_NUMBER"*.
381
403
  The value of **"s04_remove_columns"** is a list of column numbers to
382
- remove. (For columns references *"BY_NAME"* see **"s10_column_order"**.)
404
+ remove. (For column references *"BY_NAME"* see **"s10_column_order"**.)
383
405
 
384
406
  ### "s05_merge_columns"
385
407
 
386
- The key **"s05_merge_columns"** have an array of merges to be done.
408
+ The key **"s05_merge_columns"** has an array of merges to be done.
387
409
  Each merge have the keys **"columns"** and **"separator"**.
388
410
 
389
411
  **"columns"** have a list of column references. If *"BY_NAME"* the
@@ -399,16 +421,16 @@ the column values being merged.
399
421
  The key **"s06_place_columns_first"** has a value that is a list of the
400
422
  column numbers to be placed first in order. This step re-orders the
401
423
  columns.
402
- (For columns references *"BY_NAME"* see **"s10_column_order"**.)
424
+ (For column references *"BY_NAME"* see **"s10_column_order"**.)
403
425
 
404
426
  ### "s07_rename_columns"
405
427
 
406
428
  The key **"s07_rename_columns"** has a value that is a list of column rename
407
429
  operations. Each column rename operation has the keys **"column"** and **"name"**.
408
430
 
409
- **"column"** is the number/name of the column before renameing. This is a
431
+ **"column"** is the number/name of the column before renaming. This is a
410
432
  column number in the case of *"BY_NUMBER"*, and a column name/title
411
- in the sace of *"BY_NAME"*.
433
+ in the case of *"BY_NAME"*.
412
434
 
413
435
  **"name"** is the new name/title of the column identified by **"column"**.
414
436
 
@@ -443,7 +465,7 @@ keys. **"kind"** can have the values: *"STRIP"*, *"REMOVECHARS"*,
443
465
  **"kind"** value *"STRIP"* shall have the keys: **"kind"**, **"case"**, **"chars"**
444
466
  and **"column"**. This case means that the characters in **"chars"** shall
445
467
  be stripped off the beginning and end of the column value. If key
446
- **"chars"** is empty string, then white space is stripped off.
468
+ **"chars"** is empty string, then whitespace is stripped off.
447
469
 
448
470
  **"kind"** value *"REMOVECHARS"* shall have the keys: **"kind"**, **"case"**,
449
471
  **"chars"** and **"column"**. This case means that the characters in **"chars"**
@@ -461,7 +483,7 @@ and if a sub-string of the column value equals this string that part is
461
483
  replaced with the value of key **"to"**.
462
484
 
463
485
  **"column"** identifies the column to rewrite. This is a column number in the
464
- case of *"BY_NUMBER"*, and a column name/title in the sace of *"BY_NAME"*.
486
+ case of *"BY_NUMBER"*, and a column name/title in the case of *"BY_NAME"*.
465
487
 
466
488
  **"chars"** is a list of characters written as a string. These characters
467
489
  are removed or stripped off the beginning/end depending on the **"kind"**
@@ -471,8 +493,8 @@ value.
471
493
  value of **"from"** shall be case sensitive or not. Possible values are
472
494
  *"MATCH_CASE"* and *"IGNORE_CASE"*.
473
495
 
474
- **"from"** specifies what the part of the column value shall be to substituted
475
- when matching. The from part in the substitute from something to something.
496
+ **"from"** specifies what part of the column value shall be substituted
497
+ when matching.
476
498
 
477
499
  **"to"** specifies the string that substitution will replace **"from"** with.
478
500
 
@@ -485,22 +507,21 @@ Columns not mentioned in **"s10_column_order"** will not be output,
485
507
  and will thus be removed.
486
508
  (For *"BY_NUMBER"* see **"s04_remove_columns"** and **"s06_place_columns_first"**.)
487
509
 
488
- ## Backward compatibility of configuration keywords
510
+ ## Utility for recoding text files
489
511
 
490
- Old keywords according to the table below are automatically renamed to the new keywords, when reading the configuration file.
512
+ When working with text based files like comma separated values (CSV)
513
+ the file may have an incorrect character encoding, and even worse
514
+ you may not know what character encoding was used to create the file.
515
+ As a small tool for these situations the excel-list-transform includes
516
+ a small recode utility. Using this you can by trial and error recode
517
+ from different encodings until you find which encoding works. (This
518
+ may be the way to figure out which character encoding to write into
519
+ a configuration file.)
491
520
 
492
- | Version 0.7.13 and lower | Version 0.8 and higher |
493
- |--------------------------|-------------------------|
494
- | - | s01_split_rows |
495
- | - | s02_merge_rows |
496
- | s1_split_columns | s03_split_columns |
497
- | s2_remove_columns | s04_remove_columns |
498
- | s3_merge_columns | s05_merge_columns |
499
- | s4_place_columns_first | s06_place_columns_first |
500
- | s5_rename_columns | s07_rename_columns |
501
- | s6_insert_columns | s08_insert_columns |
502
- | s7_rewrite_columns | s09_rewrite_columns |
503
- | s8_column_order | s10_column_order |
521
+ ```python
522
+ python3 -m excel_list_transform.recode --help
523
+ python3 -m excel_list_transform.recode -i a.txt -o b.txt --from cp1250 --to utf-8
524
+ ```
504
525
 
505
526
  ## Source code
506
527
 
@@ -508,7 +529,9 @@ Source code and tests are available at [https://bitbucket.org/tom-bjorkholm/exce
508
529
 
509
530
  ## Test summary
510
531
 
511
- * Test result: 4119 passed in 14s
512
- * No Flake8 warnings.
513
- * No mypy errors found.
514
- * 0.8.4 built and tested using python version: Python 3.12.6
532
+ - Test result: 1368 passed in 64s (0:01:04)
533
+ - No flake8 warnings.
534
+ - No mypy errors found.
535
+ - No python layout warnings.
536
+ - Built version(s): 0.9
537
+ - Build and test using Python 3.14.5
@@ -0,0 +1,116 @@
1
+ # excel-list-transform
2
+
3
+ ## Background
4
+
5
+ This python application was born out of an experience at sail racing events. At the start of the events we received an excel list with participants (from a registration web) to enter into the scoring software and into tool for online notice board. The information was present in the excel file, but the columns were all wrong. To avoid the stressful manual rework of the information in the excel list this application was created.
6
+
7
+ ## Using it
8
+
9
+ If you want to use it install it using pip from [https://pypi.org/project/excel-list-transform](https://pypi.org/project/excel-list-transform).
10
+ There is no need to download anything from Bitbucket to use the application.
11
+
12
+ ### Installing on mac and Linux
13
+
14
+ ````sh
15
+ pip3 install --upgrade excel-list-transform
16
+ ````
17
+
18
+ ### Installing on Microsoft Windows
19
+
20
+ ````sh
21
+ pip install --upgrade excel-list-transform
22
+ ````
23
+
24
+ ### Information for use
25
+
26
+ Please see [https://pypi.org/project/excel-list-transform](https://pypi.org/project/excel-list-transform) or please see README_pypi.md
27
+
28
+ ## What it does
29
+
30
+ This small python application:
31
+
32
+ - reads data (that is a list with columns) from an excel file, an ODS file,
33
+ or from a comma separated values (CSV) file.
34
+ - splits columns in the list (like creating "first name" and "last name"
35
+ columns from "name" column)
36
+ - merges columns in the list (like creating "name" column from "first name"
37
+ and "last name" columns)
38
+ - removes columns in the list
39
+ - reorders columns in the list
40
+ - renames columns in the list
41
+ - inserts columns in the list
42
+ - rewrites columns in the list (like transforming telephone numbers from
43
+ local/national format to international format)
44
+ - writes the resulting data (that is a list with columns) to an excel file,
45
+ an ODS spreadsheet file, a comma separated values (CSV) file, or
46
+ any of a number of other file formats.
47
+
48
+ How this is done is governed by a configuration file. The application can create a number of example configuration files with accompanying description text files.
49
+
50
+ ## Cloning
51
+
52
+ This repository uses submodules. Clone it with:
53
+
54
+ ```sh
55
+ git clone --recurse-submodules \
56
+ git@bitbucket.org:tom-bjorkholm/excel-list-transform.git
57
+ ```
58
+
59
+ If you already cloned without submodules, initialize them with:
60
+
61
+ ```sh
62
+ git submodule update --init --recursive
63
+ ```
64
+
65
+ To update the checked-out submodule revisions:
66
+
67
+ ```sh
68
+ git submodule update --remote --merge
69
+ ```
70
+
71
+ ## Supported Python versions
72
+
73
+ - Package runtime baseline: Python 3.13 or newer
74
+ - Maintainer validation target: Python 3.13, and 3.14
75
+ - Main day-to-day development: usually the newest supported Python version
76
+
77
+ ## Development workflow
78
+
79
+ On macOS and Linux, the normal workflow is:
80
+
81
+ 1. Run `./run_setup_build_environment.py` once after cloning or when the
82
+ build environment needs to be recreated.
83
+ 2. Run `./run_build.py` for the normal build-and-test cycle.
84
+ 3. Run `./run_clean_build.py` before review or release work that needs a
85
+ completely fresh build.
86
+
87
+ The helper scripts are:
88
+
89
+ - `run_setup_build_environment.py`
90
+ Create or refresh the build environment.
91
+ - `run_build.py`
92
+ Build the package and run the configured checks in the project virtual
93
+ environment.
94
+ - `run_clean.py`
95
+ Remove files generated by the build system.
96
+ - `run_clean_build.py`
97
+ Perform a clean build from scratch. This is especially useful because some
98
+ duplicate-code diagnostics only appear on a clean build.
99
+ - `run_pypi_build.py`
100
+ Create the distribution artifacts intended for PyPI publishing.
101
+
102
+ The standard verification suite includes pytest, pylint, flake8, and mypy.
103
+ After a build, the generated reports can be browsed through
104
+ `reports/index.html`.
105
+
106
+ After running `run_build.py` or `run_clean_build.py`, you can manually test
107
+ the built and installed application in the virtual environment `./venv`.
108
+
109
+ ## Test summary
110
+
111
+ - Test result: 1368 passed in 64s (0:01:04)
112
+ - No flake8 warnings.
113
+ - No mypy errors found.
114
+ - No python layout warnings.
115
+ - Built version(s): 0.9
116
+ - Build and test using Python 3.14.5