-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathConvertTextNumbersToNumbers.py
More file actions
172 lines (139 loc) · 6.45 KB
/
ConvertTextNumbersToNumbers.py
File metadata and controls
172 lines (139 loc) · 6.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# -*- coding: utf-8 -*-
from Npp import editor
import os
import re
import configparser
from typing import Any, Union
import locale
from decimal import Decimal
SCRIPT_NAME = "ConvertTextNumbersToNumbers"
# Wim Gielis
# Mar. 2025
#
# ConvertTextNumbersToNumbers script (Alt-l):
# - The selection is in a tabular format with a clear separator
# - Provide a field separator and column(s) to convert to numbers and number locales.
# - Transformations:
# * trim spaces
# * minus sign taken from the back
# * brackets are negative
# * interpretation of separators for decimals and thousands through locales
# - The chosen settings will be stored/retrieved from an ini configuration file
def convert_text_to_number(value: str, number_locale) -> Union[float|int]:
# No whitespace
text_number = value.strip()
# Currency logic
currency = 0
currency_items_to_check = ['€', '$', '£', 'EUR', 'USD', 'GBP']
pattern = '|'.join(map(re.escape, currency_items_to_check))
match = re.search(pattern, value)
if match:
value = re.sub(pattern, '', value)
currency_designation = match.group()
currency = 1
if text_number in ['', '-']:
return 0
# Remove surrounding double quotes
if text_number.startswith('"') and text_number.endswith('"'):
text_number = text_number[1:-1]
# Minus sign at the end or brackets: take it out
factor = 1
if text_number[-1] == '-':
factor = -1
text_number = text_number[:-1]
elif text_number.startswith('(') and text_number.endswith(')'):
factor = -1
text_number = text_number[1:-1]
if text_number[-1] == '%':
factor *= 0.01
text_number = text_number[:-1]
# Try the conversion to a number
try:
locale.setlocale(locale.LC_ALL, number_locale) # Set the chosen locale
numeric_number = factor * float(locale.atof(text_number))
if isinstance(numeric_number, float) and numeric_number.is_integer():
return int(numeric_number)
else:
return numeric_number
except ValueError:
return value
def format_number(value, number_locale) -> str:
try:
locale.setlocale(locale.LC_ALL, number_locale)
return str(Decimal(value))
except:
return value
# Get script directory (same as script location) for the configuration file
script_path = notepad.getPluginConfigDir()
ini_file = os.path.join(script_path, "config.ini")
# Create a ConfigParser instance
config = configparser.ConfigParser()
# Read the INI file if it exists
if os.path.exists(ini_file):
config.read(ini_file)
# Define the section for this script
script_section = SCRIPT_NAME
continue_script = True
if continue_script:
# Ask for a field separator, but try to get if from the configuration file
field_separator = config.get(script_section, "field_separator", fallback=None)[1:-1]
field_separator = notepad.prompt("Please provide the field separator:", "Search string", field_separator)
if not field_separator:
notepad.messageBox( "Error: No field separator provided!", "Invalid entry", MESSAGEBOXFLAGS.OK + MESSAGEBOXFLAGS.ICONSTOP )
continue_script = False
else:
field_separator = field_separator.strip().encode().decode('unicode_escape')
if continue_script:
# Ask for the columns to convert, but try to get if from the configuration file
columns_to_convert = config.get(script_section, "columns_to_convert", fallback=None)[1:-1]
columns_to_convert = notepad.prompt("Which columns do you want to convert (comma-separated, 1-based indices):", "Columns to convert", columns_to_convert)
if not columns_to_convert:
notepad.messageBox( "Error: No column numbers provided!", "Invalid entry", MESSAGEBOXFLAGS.OK + MESSAGEBOXFLAGS.ICONSTOP )
continue_script = False
if continue_script:
# Ask for the input locale, but try to get if from the configuration file
input_locale = config.get(script_section, "input_locale", fallback=None)[1:-1]
input_locale = notepad.prompt("Please provide the field separator:", "Input locale", input_locale)
if not input_locale:
notepad.messageBox( "Error: No input locale provided!", "Invalid entry", MESSAGEBOXFLAGS.OK + MESSAGEBOXFLAGS.ICONSTOP )
continue_script = False
else:
input_locale = input_locale.strip()
if continue_script:
# Ask for the output locale, but try to get if from the configuration file
output_locale = config.get(script_section, "output_locale", fallback=None)[1:-1]
output_locale = notepad.prompt("Please provide the field separator:", "Output locale", output_locale)
if not output_locale:
notepad.messageBox( "Error: No output locale provided!", "Invalid entry", MESSAGEBOXFLAGS.OK + MESSAGEBOXFLAGS.ICONSTOP )
continue_script = False
else:
output_locale = output_locale.strip()
if continue_script:
# Ask for the output custom format, but try to get if from the configuration file
output_custom_format = config.get(script_section, "output_custom_format", fallback=None)[1:-1]
output_custom_format = notepad.prompt("Please provide the field separator:", "Output custom format", output_custom_format)
if not output_custom_format:
notepad.messageBox( "Error: No output locale provided!", "Invalid entry", MESSAGEBOXFLAGS.OK + MESSAGEBOXFLAGS.ICONSTOP )
continue_script = False
else:
output_custom_format = output_custom_format.strip()
if continue_script:
selected_text = editor.getSelText()
if not selected_text.strip():
editor.messageBox("No text selected!", "Error", 0)
else:
lines = selected_text.split("\n")
processed_lines = []
for line in lines:
if not line.strip():
processed_lines.append(line)
continue
fields = line.split(field_separator)
for col in columns_to_convert.split(','):
col_2 = int(col) - 1
if col_2 < len(fields):
fields[col_2] = format_number(convert_text_to_number(fields[col_2], input_locale), output_locale)
processed_lines.append(field_separator.join(fields))
if processed_lines:
new_text = "\n".join(processed_lines)
editor.replaceSel(new_text)