Skip to content
maforget edited this page Sep 12, 2025 · 12 revisions

Basic

Set it up in the Preferences => Library (at the bottom). There are 10 available Virtual Tags. They can be used as sorting, grouping, stacking and Smart Lists. It uses the same feature that sets the caption in the ComicRack.ini.

To format numbers refer to this page on Microsoft's site. In the documentation linked you will see something like {0:000}, you basically just need to enter the 000. The rest is auto inserted, so you could technically pretty much do all the formatting that is linked.

Warning

Known Problem:

This feature is not backward compatibles, backup your DB before using it. The reason is that if the new columns & smart lists are saved inside your Database & Settings file. If for example you create a smart list containing one of the new Virtual TAG and decide to go back to the OG version, an older release or simply a version without this feature it will reset your database. If you ever want to go back make sure you don't have any smart lists that contains the Virtual Tags.

TO DO:

  • Basic functions are in, just no UI. Read the documentation below.
  • Have an option so that the caption can be set from a Virtual Tag from the software, instead of going the ComicRack.ini route. (You can kind of do it by changing the field under the thumbnails from Caption to your Virtual Tag.

Syntax (spaces added for clarity):

So the syntax is:

[ prefix { fieldName } suffix ]

For numbering:

[ prefix { fieldName:numberFormat } suffix ]

While using a custom field, just double up the curly brackets:

[ prefix {{ fieldName }} suffix ]

Here are some examples from the ComicRack.ini file:

Format of eComic captions

  • [{format} ][{series}][ - {title}][ {volume}][ #{number}][ ({year}[/{month}])]

Same as above but with numbering format

  • [{format} ][{series}][ - {title}][ V{volumeonly:00000}][ #{numberonly:000} [of {count}]][ ({year}[/{month}])]

Export File Naming

  • [{format} ][{series}][ {volume}][ #{number}][ ({year}[/{month}])]

You can embed a field inside another or even insert a reference to another Virtual Tag. Just don't reference a tag inside itself, it will crash the program. I did add a small protection so you can't save it or add it.


Advanced (using functions)

There is no UI to use these currently, you must refer to the documentation below. If you have any errors in your Virtual Tags, an error message will be output in the tag. So add the column to your view while modifying it. You will need to press Apply or Ok in the preferences dialog to update the values, since they are now cached.

Note

  • Functions names are not case sensitive.
  • Functions find themselves between square brackets. [ or ]
  • Prefix a function name with a $.
  • Wrap the function parameters with < & >.
  • Refer to a book field by surrounding the word with curly brackets. Ex: {Series} or {{CustomField}}
  • Special characters needs to be escaped with the \. Usually, $, <, > but also {, }, [, ], \.
  • All parameters are required.

Functions

Category: Text

Tip

You will need to escape \ the regex escape character \ if used in a regex pattern. When Regex Replace doesn't match anything it will return the input text. Regex are set to be case insensitive.

Example: Matching text that is around a parenthesis.

  • \(.+\) => Matching an actual parenthesis needs to be escaped in normal regex.
  • \\(.+\\) => You will need to double the escape character \ in your pattern. Parenthesis aren't a special character.

Example: Using capturing groups:

  • .+(\(.+\)) // $1 => Match everything and create a capturing group containing what is in parenthesis. The capturing group in C# is prefixed by a $.
  • .+(\\(.+\\)) // \$1 => Like above escape only the \ in the pattern. But we need to escape the $ in, since this is a special character.

Regex Match: Outputs a boolean indicating whether the regex matched.

$regexmatch<string inputText, string pattern>

Regex Replace:

$regexreplace<string inputText, string pattern, string replacement>

Substring: Setting the length to -1 (or bigger than the remaining length) will capture the remainder of the string.

$Substring<string text, int startIndex, int length>

Escape: Escapes special characters in a string when writing a C# expressions. Since you can't use a verbatim literal string (prefixing a string with @), this function will escape the string for special characters. This doesn't replace the requirement to escape special character $, <, >, like mentioned above. Text written in the Caption box still needs to be escaped, this function is used when a C# string needs to be escape, like when referring to a field in an expression. Ex: To get the length of the File Path [$expr<"$escape<{FilePath}>".Length>]

$escape<String Text>

Category: Math

Expression: This will run a C# expression and output it's result as a string. It can be code, math, etc. See special note about expressions.

$expr<string value> => Runs a C# expression

Int: This will parse your text as an integer. Will return -1 if not an integer.

$int<string intInText> - return type is a Int32

Double: This will parse your text as a double. Will return -1.0 if not a double.

$double<string doubleInText> - return type is a Double

Category: Date

Date Format: This will parse your text as a date and apply formatting using the C# standard or custom format. Leave the format field empty if no formatting is required.

$date<string dateInText, string format>

Day: This will parse your text as a date and output the day (padded by 0).

$day<string dateInText>

Month: This will parse your text as a date and output the month (padded by 0).

$month<string dateInText>

Year: This will parse your text as a date and output the year.

$year<string dateInText>

Category: Boolean

If: The first condition parameter is evaluated as a boolean C# expression. See special note about expressions.

$if<string condition, string ifTrue, string ifFalse>

Not: This will evaluate the text as a boolean C# expression and return the inverse. See special note about expressions.

$not<string value>

Expression

These are C# code that is evaluated by a library called Dynamic Expresso. Test it online with this link.

Important

  • C# code requires you to wrap text in quotation marks. "Manga"
  • Required only when using a function with the parameter that is evaluated as an expression. $if, $not & $expr 1st parameter are affected only.
  • When referencing a field in a C# expression, you will need to wrap that field by quotation marks to indicate it is a string in regards to C#. "{Tags}".Contains("Manga")
  • true and false need to be lower case and not wrapped in quotation marks to be considered by Dynamic Expresso.
  • Dynamic Expresso evaluation will only occur if the C# default parser didn't work. Examples: True, "Text"=="Text", true, false || true or $not<"{Tags}".Contains("Manga")>. But not Text==Text, "false" || "true" or "True"

Examples

These aren't meant to be super useful. Just examples of the syntax and possibility.

Series (Year). Just using Added Time for demonstration purpose only.

[$if<$not<"{Tags}".Contains("Manga")>,{Series} ($year<{AddedTime}>), {Series}>]

Selecting the 1st word from a Series, using expressions.

[$expr<"{Series}".Split(' ').FirstOrDefault()>]

Selecting the 1st word from a Series, using substring. Both output the same thing, this one is just more complex.

[$substring<{Series},0, $expr<"{Series}".Split(' ').FirstOrDefault()?.Length>>]

Escaping special characters. We need to escape \ the > so it doesn't believe it is the end of the function. The \ is removed when being evaluated as C#, so it will be evaluated to 10 > 1.

[$if<$not<10 \> 1>,10 is bigger than 1, 10 isn't bigger than 1>]

Using the escape function. Returns the length of the file path (to check for long file path that could be problematic). Because of the backslash \ in the File Path the expressions can't handle it.

[$expr<"$escape<{FilePath}>".Length>]

Remove parentheses. Replacing them with nothing.

[$regexreplace<{Series},\\(.+\\),>]

Replace all the text by what is in the capture group 1. Only works when parenthesis are present, since the regex will not match in that condition it returns the original input text.

[$regexreplace<{Series},.+(\\(.+\\)),\$1>]

Actually useful usage examples (copied from this post)

The Main way I am using them is grouping by SeriesGroup - Series, so seemingly different series are grouped together. Useful when looking at a whole Library. This could be done via pressing Ctrl while grouping, but the issue with that is that when a field is empty it, that empty field would return Unspecified (so Unspecified - Series, not very useful). This way if a field like SeriesGroup is empty it just doesn't show it.

[{SeriesGroup} - ][{Series}]

Another way is grouping using Series - Format. I usually prefer TPB, but when applicable I will get individual chapters to finish the series while the TPB aren't available. So I would have the TPB on top and the Chapters below. Again Ctrl would result in an empty field returning Unspecified, this way the empty format are on top).

When the main series has no Format:

[{Series}][ - {Format}]

More complex when the Format is also TPB, It keeps the Format but removes it when it is Trade Paper Back:

[{Series}][ - $if<"{Format}"=="Trade Paper Back",,{Format}>]

Another use might be to just use another name for a field, So you could refer to Web as ID for example. This could also be done by adding the data to a custom field:

[{Web}]

But, contrary to custom field, Virtual Tags are available in the Search Browser, so you could create a Virtual Tag that refers to a custom field and use it in the Search Browser:

[{{comicvine_volume}}]

Someone wanted to show the Format only for certain format. https://www.reddit.com/r/comicrackusers/comments/1fz9zx3/comment/lr076c2/

[$if<"{Format}"=="Annual" ||  "{Format}"=="Special",[{format} ][{series}][ {volume}][ #{number}][ - {title}][ ({year}[/{month}[/{day}]])],[{series}][ {volume}][ #{number}][ - {title}][ ({year}[/{month}[/{day}]])]>]

Someone wanted to have either the a Custom field called Event Year appear and if not available then show the Volume. https://github.com/maforget/ComicRackCE/issues/93

[$if<"{{Event Year}}" == "", {volumeonly}, {{Event Year}}>]

You could format numbers to be 0 padded for example:

[{Number:00}]

You can replace the Caption (the text that appears below thumbnails) in some Layout only. Copy the ComicCaptionFormat from the ComicRack.ini and use it in the Virtual Tags (it uses the same engine), for example having a Caption (No Format. Remove the Format part, change the Caption field for thumbnails to your Caption (No Format), save the layout to be reusable easily. You can have a layout where the text under your thumbnails doesn't show the Format and you didn't have to change the ComicCaptionFormat for all thumbnails and can set it like you like.

[{series}][ {volume}][ #{number}][ - {title}][ ({year}[/{month}[/{day}]])]

Here is another way I am using them. Instead of just using SeriesGroup - Series I also use Series Group OR Series as a group. Since I also use group headers if you have multiple Series in a Series group it can clutter it. So it this now groups by series group if they exists but series if it doesn't. In addition you could also stack by Series with the Volume (by using Ctrl to stack by multiples or create another vtag).

[$if<"{SeriesGroup}"=="",{Series},{SeriesGroup}>]

Extracts the first letter and also output 0 - 9, when it's a number. You can also reference other Virtual Tags, in this case VirtualTag02.

[$if<$int<$substring<{VirtualTag02},0,1>> == -1,$substring<{VirtualTag02},0,1>,0 - 9>]

Clone this wiki locally