# An efficient method for assigning numeric inputs into %output%

**URL:** https://community.mp3tag.de/t/an-efficient-method-for-assigning-numeric-inputs-into-output/63206
**Category:** Web Sources Discussion
**Created:** [December 25, 2023, 10:55pm UTC](https://community.mp3tag.de/t/an-efficient-method-for-assigning-numeric-inputs-into-output/63206 "2023-12-25T22:55:26Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![rboss](https://community.mp3tag.de/letter_avatar_proxy/v4/letter/r/5f9b8f/32.png) [@rboss](https://community.mp3tag.de/u/rboss)
#### Post date: [December 25, 2023, 10:55pm UTC](https://community.mp3tag.de/t/an-efficient-method-for-assigning-numeric-inputs-into-output/63206/1 "2023-12-25T22:55:26Z")

</div>

I had been working on a way to select/input cover size for an iTunes source script for quite some time; and with the new features of Mp3Tag v3.22+, I developed a method to do it (more or less).

Since this method can work with any number, and I was unable to find any topic (other than my [own](https://community.mp3tag.de/t/suggestion-splice-command-for-ws/61854)) regarding this subject, I've created this topic to explain how I did it, so other authors can benefit from it.

Until v3.22, there was only one field available for direct user input - `[SearchBy]`. With v3.22, the introduction of a settings schema now allowed adding string, boolean and integer values from outside of a script, and the ability to refer to them using `ifVar` or `ifNotVar`. For example, setting the number '5' in the schema, like

```
{
  "type": "number",
  "key": "testNumber",
  "title": "Something to enter a number",
  "description": "Enter a number",
  "default": 42
},

```

creates a input field with "42" pre-written (but this can be replaced with "5"). This field could then be called from the script, like

```
IfVar "testNumber" "5"
...
Say "5"
...
EndIf

```

in a simple manner. In this example, the number '5' is indirectly 'translated' from a 'Settings' value into a script value. With a minor tweak, it could even be stored in an output, like

```
IfVar "testNumber" "5"
   OutputTo "testNumber"
   Say "5"
EndIf

```

so that this value could now be called further down with `sayOutput "testNumber"`.

But this only works for a single number. Typing any number other than '5' in the input field won't return any value in the script. For it to work with a number _range_, `ifVar` conditions must be set for each number in the range. For a range [0-9}, this would mean

```
IfVar "testNumber" "0"
   OutputTo "testNumber"
   Say "0"
EndIf
IfVar "testNumber" "1"
   OutputTo "testNumber"
   Say "1"
EndIf
IfVar "testNumber" "2"
   OutputTo "testNumber"
   Say "2"
EndIf
...
IfVar "testNumber" "9"
   OutputTo "testNumber"
   Say "9"
EndIf

```

So, 4 lines of code per digit x 10 possible numbers = 40 lines of code for a single-digit number to be translated. This can be further optimized, by replacing both `outputTo "testNumber"` and `say "N"` commands with `set "testNumber" "N"`. So, 3 lines \* 10 = 30 lines of code; which is perfectly doable.

With a 2-digit number range [00-99], it would take 3 \* 100 = 300 lines of code; which is unpractical, but still doable. Bigger numbers (like a cover size in pixels, which range in the thousands) would be extremely impractical and very resource-heavy for a script to process.

An easier way to translate 2-digit numbers is to split them into 2 single-digit inputs in the schema, translate each one separately into the script with `ifVar`, and then join the 2 outputs back into a 2-digit number, like

```
OutputTo "fullNumber"
   Say "testNumber1"
   Say "testNumber2"

```

Translating the number "42" can now be done by inputting "4" into `"testNumber1"` and "2" into `"testNumber2"` in the schema, using 2 sets of `ifVar` for each digit, and ending with `outputTo "fullNumber"` to merge the 2 digits back into "42". This would take 3\*10 \* 2 (sets of `ifVar`) + 3 lines for outputting `"fullNumber"` = 63 lines of code. Which is far less than the 300 lines needed before, but is still quite a sum.

I've improved this concept, and managed to translate a 4-digit number in 23 lines of code. It requires use of Mp3Tag 3.23, JSON tools and `%output%` buffer referral. If you don't know how these tools works, you may not fully understand the following.

For a 2-digit number (like "42"), on the configuration schema side, simply create 2 number input fields; one for each digit of the number we want. That's all that is necessary from this end.

In the script, using `json_foreach`, it's possible to iterate over a JSON-formatted data array and perform actions for each element in that array. If our input data had an array with the single-digit numbers, it could be accessed and parsed into `"testNumberN"`.

But normally, input data doesn't have those values, or it may not be JSON data at all.

What to do? Write our own JSON array!  
How?

First, we clear the current buffer; this can be achieved with a [regular expression](https://docs.mp3tag.de/regex/) (you may want to learn about those too) like

```
RegexpReplace "^.*" ""

```

Next, we write a JSON-formatted array into the buffer; for efficiency, I'm adding this step into the previous one, like

```
RegexpReplace "^.*" "{"array":[{"number":0},{"number":1},{"number":2},{"number":3},{"number":4},{"number":5},{"number":6},{"number":7},{"number":8},{"number":9}]}"

```

Next, we need to tell Mp3Tag to consider the text currently in the buffer as JSON data, which is done with

```
json "on" "current"

```

Now we are working in JSON "mode" and have a JSON array with [0-9]. Next we'll check its contents sequentially and use them as needed. Let's say

```
json_foreach "array"
   json_select "number"
   OutputTo "digit"
   SayRest
json_foreach_end

```

This reads _-- for all elements in the array, select the` "number"` elements, and write them to `"digit"`--_.  
The output `digit` will be filled with each value in the array, step by step: "0", then "01", 012", "0123", "01234", "012345", "0123456", "01234567", "012345678", and "0123456789".

Now lets add an `ifVar`

```
json_foreach "array"
   json_select "number"
   OutputTo "digit"
   SayRest

   IfVar "testNumber1" "%digit%"
	   OutputTo "testNumber1"
	   SayRest
   EndIf

json_foreach_end

```

This is the same `ifVar` command as shown before; the only difference is that instead of comparing `"testNumber1"` to a number, it is now comparing with the current value of `"digit"` (which is being filled step-by-step with the values in the array, which are numbers). Going back to our number "42", which was split into `"testNumber1"` (4) and `"testNumber2"` (2), this loop now processes as follows

```auto
Loop 1: Select array value "0" / Output to "digit":"[empty]" / Write "0" into "digit" / IfVar "testNumber1" (4) is %digit%" (0) / false
Loop 2: Select array value "1" / Output to "digit":"0" / Write "1" into "digit" / IfVar "testNumber1" (4) is %digit%" (01) / false
Loop 3: Select array value "2" / Output to "digit":01 / Write "2" into "digit" / IfVar "testNumber1" (4) is %digit%" (012) / false
Loop 4: Select array value "3" / Output to "digit":"012" / Write "3" into "digit" / IfVar "testNumber1" (4) is %digit%" (0123) / false
...
Loop 10: Select array value "9" / Output to "digit":"012345678" / Write "9" into "digit" / IfVar "testNumber1" (4) is %digit%" (0123456789) / false

```

Our output `"testNumber1"` stayed empty because `ifVar` never matched `"testNumber1"` (4) with `"digit"`, because the contents of `"digit"` were being appended to the end of the its current value.  
Let's try again, but now we clear `"digit"` at the end of each loop:

```
json_foreach "array"
   json_select "number"
   OutputTo "digit"
   SayRest

   IfVar "testNumber1" "%digit%"
     OutputTo "testNumber1"
     SayRest
   EndIf

   Set "digit"
json_foreach_end

```

Running our (modified) loop again

```auto
Loop 1: Select array value "0" / Output to "digit":"[empty]" / Write "0" into "digit" / IfVar "testNumber1" (4) is %digit%" (0) / false / Clear "digit":"0"
Loop 2: Select array value "1" / Output to "digit":"[empty]" / Write "1" into "digit" / IfVar "testNumber1" (4) is %digit%" (1) / false / Clear "digit":"1"
Loop 3: Select array value "2" / Output to "digit":"[empty]" / Write "2" into "digit" / IfVar "testNumber1" (4) is %digit%" (2) / false / Clear "digit":"2"
Loop 4: Select array value "3" / Output to "digit":"[empty]" / Write "3" into "digit" / IfVar "testNumber1" (4) is %digit%" (3) / false / Clear "digit":"3"
Loop 5: Select array value "4" / Output to "digit":"[empty]" / Write "4" into "digit" / IfVar "testNumber1" (4) is %digit%" (4) / TRUE / OutputTo "testnumber1":"[empty]" / Write "4" into "testnumber1" / Clear "digit":"4"
Loop 6: ...
...
Loop 10: ...

```

Success! "4" has been written into `"testNumber1"`. The rest of the loop will still run, but since there will be no match, it isn't important.

As we have done for `"testNumber1"`, let's add `"testNumber2"` and check both at the same time

```
json_foreach "array"
   json_select "number"
   OutputTo "digit"
   SayRest

   IfVar "testNumber1" "%digit%"
      OutputTo "testNumber1"
      SayRest
   EndIf

   IfVar "testNumber2" "%digit%"
      OutputTo "testNumber2"
      SayRest
   EndIf

   Set "digit"
json_foreach_end

```

Now, after `"testnumber1"` (4), `"testnumber2"` (2) will be compared with the current value of `"digit"`. When it matches, that value is written into its dedicated output `"testNumber2"`. When it doesn't match, the loop keeps running until it does, then continues until the last array element has been checked.

Finally, after having both outputs (now set at "4" and "2"), we can do as before

```auto
OutputTo "fullNumber"
	Say "testNumber1" (4)
	Say "testNumber2" (2)

```

And we get our `"fullNumber"` (42)

The entire code from start to finish reads

```auto
RegexpReplace "^.*" "{"array":[{"number":0},{"number":1},{"number":2},{"number":3},{"number":4},{"number":5},{"number":6},{"number":7},{"number":8},{"number":9}]}"

json "on" "current"

json_foreach "array"
	json_select "number"
	OutputTo "digit"
	SayRest

	IfVar "testNumber1" "%digit%"
		OutputTo "testNumber1"
		SayRest
	EndIf

	IfVar "testNumber2" "%digit%"
		OutputTo "testNumber2"
		SayRest
	EndIf

	Set "digit"
json_foreach_end

OutputTo "fullNumber"
	Say "testNumber1"
	Say "testNumber2"

```

A 2-digit integer has indeed been translated from 2 user input fields from the Settings menu into a `"fullNumber"` output that can now be called as needed. And (after removing whitespaces) this was done in 19 lines of code.  
Which is much less than 63, and _much_ much less than 300.

If you've read my previous post regarding this theme, I had been asking for a `"sayVar"` command to directly write input fields into the current buffer. But this method is a better fit with a `"setVar"` command, so that

`setVar "testNumber1" "testNumber1"`

would translate the `"testNumber1"` value from the schema into a `"testNumber1"` output.

As I said before, I've worked this principle into my own [WS script for iTunes](https://community.mp3tag.de/t/ws-itunes-source-script-with-multiple-search-criteria/47197/1), and managed to get a custom 4-digit number into a working value for setting cover size, and using only 23 lines of code.

If you are a fellow author and can use this method for your own needs please do so. Feedback is not necessary, but would be appreciated.

Thank you.

---

<div class="post-metadata">

### Author: ![rboss](https://community.mp3tag.de/letter_avatar_proxy/v4/letter/r/5f9b8f/32.png) [@rboss](https://community.mp3tag.de/u/rboss)
#### Post date: [August 15, 2024, 12:16am UTC](https://community.mp3tag.de/t/an-efficient-method-for-assigning-numeric-inputs-into-output/63206/2 "2024-08-15T00:16:35Z")

</div>

Here is a simpler (and a little more efficient) method; one that doesn't require the use of JSON tools at all (and thus is simpler).

It follows the same method as before (loop through a set of digits, until a match to a Settings' value is found, and assign it to an output to be later combined into a number); however the command called to run this loop shifts from `json_foreach` to `Do ... While`.

Since we are no longer working with JSON data, our set of digits must not be a JSON-formatted array; but a plain string of digits (and separators), which can be written simply by

```auto
RegexpReplace "^.*" ",0,1,2,3,4,5,6,7,8,9"

```

You'll notice that the leading character in the string is a separator - `,` in this case. This is needed for the loop to run properly.

Now, the same script as in the previous post, with the new changes:

```auto
RegexpReplace "^.*" ",0,1,2,3,4,5,6,7,8,9"

Do
	OutputTo "digit"
	MoveChar 1
	SayUntil ","

	IfVar "testNumber1" "%digit%"
		OutputTo "testNumber1"
		SayRest
	EndIf

	IfVar "testNumber2" "%digit%"
		OutputTo "testNumber2"
		SayRest
	EndIf

	Set "digit"
While ","

OutputTo "fullNumber"
	Say "testNumber1"
	Say "testNumber2"

```

Because the first action applied to the pointer in the loop is "MOVE pointer BY 1", the first character must not be a part of our set of digits. I used a separator in this example, but it could just as well be any **one** (and only one) character. Now the pointer is resting on "0", and will read the string until `,` is found, after which it will rest on another `,`. At the end of each loop `While` will check if the pointer is on a separator (it hasn't moved, so it is), and start another loop.

At the last digit "9", `SayUntil ","` will read the rest of the string (because there is no trailing separator to stop it), but since only the final digit remains, that is all that will be read (and is what is wanted); the pointer will no longer rest on a separator, so `While` will fail its check, and the loop will be broken.

The separator used here is `,` but could just as well be any character (or string), as long as not present in the digits we're working with.

So then:

> [@rboss](#):
>
> A 2-digit integer has indeed been translated from 2 user input fields from the Settings menu into a `"fullNumber"` output that can now be called as needed. And (after removing whitespaces) this was done in

18 lines of code. Because there is no need for

```auto
json "on" "current"

```

this step can be removed.

As mentioned at the start of this post, this method is simpler (no JSON required), and a little more efficient (cutting 1 step from the previous method).

If you find this useful, please use it. If you have suggestions on how to improve it, please share them.

And thank you.

---

<div class="post-metadata">

### Author: ![Florian](https://community.mp3tag.de/user_avatar/community.mp3tag.de/florian/32/5759_2.png) [@Florian](https://community.mp3tag.de/u/Florian)
#### Post date: [November 15, 2025, 8:47am UTC](https://community.mp3tag.de/t/an-efficient-method-for-assigning-numeric-inputs-into-output/63206/3 "2025-11-15T08:47:58Z")

</div>

I just went through the workaround again, this is incredible!

I've just released Mp3tag v3.32 with support for `SayVar` (as described [here](https://community.mp3tag.de/t/suggestion-command-sayvar-for-accessing-configuration-settings/70129)).

---

<div class="post-metadata">

### Author: ![yorickausyps](https://community.mp3tag.de/letter_avatar_proxy/v4/letter/y/f6c823/32.png) [@yorickausyps](https://community.mp3tag.de/u/yorickausyps)
#### Post date: [November 15, 2025, 11:58am UTC](https://community.mp3tag.de/t/an-efficient-method-for-assigning-numeric-inputs-into-output/63206/4 "2025-11-15T11:58:01Z")

</div>

> [@Florian](#):
>
> I just went through the workaround again, this is incredible!

It actually reminds me of a _how to break a number lock_ and take the bicycle away 😉.

---

<div class="post-metadata">

### Author: ![rboss](https://community.mp3tag.de/letter_avatar_proxy/v4/letter/r/5f9b8f/32.png) [@rboss](https://community.mp3tag.de/u/rboss)
#### Post date: [November 16, 2025, 4:52pm UTC](https://community.mp3tag.de/t/an-efficient-method-for-assigning-numeric-inputs-into-output/63206/5 "2025-11-16T16:52:51Z")

</div>

> **[A quote from VAN GOGH](https://www.goodreads.com/quotes/700802-success-is-sometimes-the-outcome-of-a-whole-string-of)**
>
> Success is sometimes the outcome of a whole string of failures.

I can still remember vividly when -after multiple failed attempts- I ~~stumbled upon~~ found the right sequence of commands for this particular task.

And now I've been 1-upped by @Florian 🏆  
Thank You 🙌

---

<div class="post-metadata">

### Author: ![rboss](https://community.mp3tag.de/letter_avatar_proxy/v4/letter/r/5f9b8f/32.png) [@rboss](https://community.mp3tag.de/u/rboss)
#### Post date: [November 16, 2025, 5:05pm UTC](https://community.mp3tag.de/t/an-efficient-method-for-assigning-numeric-inputs-into-output/63206/6 "2025-11-16T17:05:45Z")

</div>

> [@yorickausyps](#):
>
> It actually reminds me of a _how to break a number lock_ and take the bicycle away 😉.

After the police gave me a stern warning to put an end to my bicycle-stealing career, I finally found a way to make a better use of those skills. 🤪 🤣

(This is a humorous joke, obviously 😉).

---

<div class="post-metadata">

### Author: ![system](https://community.mp3tag.de/uploads/default/original/2X/c/ce7035d426cb755a7916793326d23b465222a407.png) [@system](https://community.mp3tag.de/u/system)
#### Post date: [December 16, 2025, 5:06pm UTC](https://community.mp3tag.de/t/an-efficient-method-for-assigning-numeric-inputs-into-output/63206/7 "2025-12-16T17:06:40Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
