Media Center expression language-NEW: Difference between revisions

From wiki.jriver.com
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
====ListCount(...): Returns the number of items in a delimited list====
==Using this page==
The 'Contents' box above contains a list of available functions roughly grouped by usage scenario, and each function name gives a fair indication of what it might do. Each of the group headers contain some basic information pertinent to the functions inside the group. Click on a function or function group header in the Contents box to be taken directly to more information about it on the page. At the bottom right of each section there is a "Back to top" link which will take you back up to the Contents box allowing you to quickly get to where on the page you would like to go next.
==Overview==

The J. River Media Core database engine supports Excel-style functions for use in view schemes, searches, displayed columns, and tag editing.

An expression is a mixture of text, fields, and functions. A function allows special operations to be performed. Functions are all listed with a name followed by an opening and closing parenthesis. When building expressions, the instructions you wish to pass to the function are placed inside these parenthesis, with multiple instructions separated by commas. When your expression is evaluated, any spaces entered after a comma are ignored. This allows you to compose complex expressions on multiple lines, making it easier to keep track of where you are in your expression. Occasionally, you will find that you want a space, or parenthesis character to be treated literally as part of your instructions, rather than expression syntax, and in these cases, the character is "escaped" by using a preceding forward slash. Examples using this escaping can be seen [[#Clean(...): Returns a cleaned up version of a filled in template|here]] and [[#Replace(...): Replace or remove strings from a value.|here]].
As you progress with your expression building, you will begin nesting multiple functions into a single expression; always remember that a completed expression must contain a matching number of opening and closing parenthesis in order to work reliably.

The functions available to us range from highly functional, with a broad range of applicable uses, through specialised, limited use functions that only appeal to a select group of users, to seemingly redundant functions and obscure functions that MEDIA CENTER uses internally. The functions below are listed with those with the broadest appeal at the top, and the more obscure at the bottom.

Expressions can be used in many places within MEDIA CENTER, for varying reasons. Places that you might consider using expressions include:

* The player information bar
* The image playback caption
* A view scheme search list
* The "Rename, Move or Copy Files" tool
* The tag window
* Panes (''aka categories'')
* List columns
* Thumbnail text
* The search field
* The library field manager (''Create expression based library fields'')
* Theatre View
* The links manager (''Use expressions to format the URLs for your links'')

<ins>'''Any given expression can only work on any given single file. It is not possible to compare a field in one file with a field in another file.'''</ins>

====Fields====

Any text between brackets [] will be replaced with the corresponding field from your library. As an example, [Artist] would be replaced by Bob Dylan for any Bob Dylan tracks. If the text between brackets doesn't match any known fields, it will be left alone. After the field name, a comma can be placed followed by a 0 or 1 for whether the field should get formatted. So, [Duration] and [Duration, 1] will give "4:02" while [Duration, 0] will give "242". This is particularly important when working with the "Format" functions, where most times you will want the evaluator to work with the raw field contents rather than the formatted contents you see in the file list.

Function and field values in expressions are ''not'' case-sensitive.
Available functions with descriptions and examples are listed below.

==Functions==

===If(...): Ask closed questions and control output dependent upon result.===

{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" width=100 | If()
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | ListCount()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This will be the function you will likely use more than any other. It is typically used in conjunction with one or more other functions and allows you to give specific instructions depending upon whether the result is positive (1) or negative (0). The positive instruction is always given first.
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | ListCount is used to return the number of items that exist in any given field, using any given delimiter.
|- valign="top"
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''if(''expression to test'',instructions if positive,''instructions if negative'')'''
| style="background: #ecfeea; color: black; border: 1px solid black" | '''ListCount(Field to count,Delimiter to use)'''<br>
'''Field to count''': ''Typically, this will be a list type field, but this is not compulsory. The data in any field can be parsed using any chosen delimiter''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''if(isequal([artist],bob dylan,1),Genius,Mediocre)'''<br>''Wherever this expression is applied, be it as an expression column or category, as part of a renaming rule, thumbnail text, if the artist tag is Bob Dylan, MEDIA CENTER will produce Genius, and for all other artists, it will produce Mediocre.'' The "IsEqual()" function is described in the first table below.
<br>
'''if(isequal([artist],bob dylan,1),Genius,if(isequal([album],Joshua Tree,8),Great Album,Mediocre))'''
<br>''Here, we have two nested "If" functions. First we ask if the artist is Bob Dylan, if the result is positive, write "Genius". If the artist is not Dylan, we then ask if the album is "Joshua Tree", if yes, write "Great Album", and if no, write mediocre''


'''Delimiter to use''': ''This is optional. If not specified, the function will default to using a semi-colon delimiter. Anything can be specified as a delimiter, from a single character to a whole word or words.''
<br>On it's own, "If()" is rather boring and not a lot of use. When used in conjunction with other functions, however, it becomes very powerful indeed. In the two examples above, the numbers 1 and 8 have been used. These are comparison mode switches used by the IsEqual function. There are 9 different compare modes in total, all of which are detailed below. Note how the second example ends with two closing parenthesis, one for each "If" function.
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>

===Query, Test and Compare using "Is" Functions===
All of the functions in this section, when used on their own, will only ever return one of two values, 1 (true) or 0 (false). There is a "[[#FormatBoolean(...): Formats a boolean (true / false) value in a specified manner|FormatBoolean()]]" function that can be wrapped around these and allows us to specify the output for each case and is discussed in more depth in the Format section. The real power and versatility of these "Is" functions is released when they are wrapped inside the If() function discussed above.

====IsEqual(...): Compares two values in one of nine specified modes====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | IsEqual()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Compares two values in one of nine specified modes ("exact match", "Is greater than" etc.) and outputs 1 for a positive match and 0 for a negative match. If no compare mode is specified, the compare will default to 0.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''isequal(''1st value to compare'',2nd value to compare'',compare mode)'''

''Available Compare Modes:''
* 0: ''case-sensitive string compare for equality''
* 1: ''case-insensitive string compare for equality''
* 2: ''numeric compare for equality''
* 3: ''numeric less than''
* 4: ''numeric less than or equal to''
* 5: ''numeric greater than''
* 6: ''numeric greater than or equal to''
* 7: ''substring search (case sensitive)''
* 8: ''substring search (case insensitive)''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''isequal([artist],[album],1)'''<br>''If the 'artist' and 'album' values are the same, the output will be 1, otherwise, the output will be 0.''

<br>'''if(isequal([artist],[album],1),Self Titled,[album])'''
<br>''Wrapped inside an 'If' function, if the 'artist' and 'album' values are the same, the output will be 'Self Titled', otherwise, the output will be the 'album' value.''

<br>'''if(isequal([artist],[album],1),Self Titled/,,[album]/))'''
<br>''This example demonstrates the character 'escaping' mentioned in the overview. Here, we want the output to be either "Self Titled," (note the inclusion of the comma) or the album value with a closing parenthesis. In order to achieve this, the comma, and the closing parenthesis, are escaped using a preceding forward-slash character. This informs the expression evaluator that these characters are not part of the expression syntax and are to be treated literally''
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====IsEmpty(...): Tests to see if a field is empty====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | IsEmpty()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Tests any given field for data. If the field is empty, the function returns 1, and if populated, the function returns 0. There are two different test modes available, a "string" test, and a "number" test. This is because as far as MEDIA CENTER is concerned, fields designated as containing numerical values that are populated with the number zero, are empty. If no test mode is specified, the function will default to 0.
Pay particular attention to the third example offered below, as it covers a caveat that comes with this particular function.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''isempty([field to test],test mode)'''
''Available test modes:''
* 0: ''String test (field must be empty to get a positive result)''
* 1: ''Numerical test (field must be empty, or contain 0 to get a positive result)''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''isempty([comment],0)'''<br>''If the comment field is empty, this expression will return 1, but if the comment field contains data, the expression will return 0.''

<br>'''isempty([track #],1)'''
<br>''This expression will perform a numerical test for data in the [track #] field. If the field is empty, or contains 0, the expression will return a positive result, 1, otherwise, the result will be negative, 0.''

<br>'''if(isempty([disc #]),,[disc #])'''
<br>''Here, by not entering any instructions to carry out for a positive result, the expression will do just that, and output nothing, but if the [disc #] field does contain data, the expression will write that out. Upon first look, you would think that this could work really well in the "Rename, Move and Copy Files" tool for only creating a \Disc #\ directory if needed. This will not work. When asking the rename tool to create directories from field data, it is smart enough to know that directories with no name are illegal in Windows, so when it encounters an empty field, it automatically converts it to "Unknown&nbsp;[Field&nbsp;Name]". It does this before the expression engine gets to see it, which means that the IsEmpty function will always return a negative result when used in the rename tool, even when the specified field is indeed empty. As we now know that empty fields are passed through the rename tool as "Unknown&nbsp;[field&nbsp;name]" we can use '''if(isequal([disc&nbsp;#],unknown,8),,[disc&nbsp;#])''' to achieve the desired result. Note that this only applies when using the rename files tool.''
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====IsRange(...): Tests a value for inclusion within a given range====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | IsRange()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | IsRange allows us to test if any given field falls inside any given range of values. If the field falls inside the given range, the function returns 1, and if outside the given range, the function returns 0.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''IsRange([Field to Test],Specified-Range)'''
''The range to test for can be letters or numbers, separated by a hyphen, without spaces, lowest value first, highest second. Letters and numbers cannot be mixed, the range can only be one or the other''
* ''1-100''
* ''a-z''
* ''c-d''
* ''23-7542''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''isrange([artist],a-c)'''<br>''Abba or Blondie will return 1 (positive), and ZZ Top will return 0 (negative).''

<br>'''if(isrange([bitrate],96-191),Poor Quality,High Quality)'''
<br>''This expression will output "Poor Quality" for any file where the bitrate fall between falls between 96 and 191, and "High Quality" for all others. Note that expressions are only as good as the instructions given, and that the above expression would label files with bitrates less than 96kbps as "High Quality". If this expression were used to add a category to a view, there would be two selectable choices in the category, Low Quality, and High Quality. Selecting either one would then filter the file list accordingly.''

<br>'''[http://yabb.jriver.com/interact/index.php?topic=38566.msg262229#msg262229 This post]''' ''on Interact shows the use of IsRange in a Search List. (right click the link, open in new tab to keep this page open). The expression format in that post shows how to form expressions for use in standard MEDIA CENTER searches, something that is also covered later'' [[#When, Where and How to use expressions|on this page.]]
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====IsMissing(...): Tests to see if a file exists on the system====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | IsMissing()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function checks to see if a file exists on the system. If the file is missing, the function returns 1 (positive), and if the file is found, the function returns 0 (negative). It is possible to specify a specific file to check for, but if you know that much, it will be quicker to fire up explorer and check yourself. This function comes in handy for checking the integrity of your MEDIA CENTER library as you can use it to produce a list of any files in your library that MEDIA CENTER cannot find. However, be aware that the larger your library, the longer this list will take to produce as MEDIA CENTER will need to physically check each files' existance in turn.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''IsMissing(Full Path To File)'''
''If no file path is specified, the function will default to checking the current file.''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''ismissing()'''<br>''Checks if the current file exists, and returns 1 (positive) if the file does not exist, and 0 (negative) if the file does exist.''

<br>'''ismissing(C:\Music\My Lost File.mp3)'''
<br>''Checks for "My Lost File.mp3" and returns 1 (positive) if the file does not exist, and 0 (negative) if the file does exist.''

<br>'''[=ismissing([filename])]=1'''
<br>''This example also demonstrates how to construct an expression for use as a MEDIA CENTER search string. If you place this in the search field in the top right corner of the program while viewing all of your library, it will filter the list, leaving only the missing files on view. If your library is in good order, this list should be empty. You could also create a view scheme and use this string in the "Set rules for file display" search to give you a view that you can visit periodically to check that your library is intact

<br>'''if(ismissing(),File is missing,File exists)'''
<br>''Wrapped inside an "If()" function, the expression outputs "File is missing" or "File Exists" depending on the result returned by IsMissing()''
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====IsRemovable(...): Tests to see if a file is stored on removable media====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | IsRemovable()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Checks to see if a file resides on removable media and if so, returns 1 (positive), and if not, returns 0 (negative). There is not a lot to say about this function, especially since MEDIA CENTER comes equipped with a [Removable] field by default that is automatically populated with 1 for all files in the library that are on removable storage. The function works in exactly the same way as the IsMissing function described above, returning 1 (positive) if the file is on removable storage, and 0 (negative) if not.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''IsRemovable(Full Path To File)'''

''If no file path is specified, the function will default to checking the current file.''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''isremovable()'''<br>''Checks if the current file is on removable storage, and if so, returns 1 (positive), if not, the function returns 0 (negative).''
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====IsInPlayingNow & IsPlaying(...): Tests to see if a file is in the Playing Now playlist or currently being played====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | IsInPlayingNow()
| rowspan="2" style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | These two functions will be dealt with together as from their names, they are self-explanatory. One checks to see if a file has been added to the playing now list in any zone, and the other checks if a file in a list is currently playing or not, in any zone. With this in mind, their most practical use is as expression columns in a file list. To add an expression column to a list, right click on any existing column header and click on the "Add expression column" option.
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | IsPlaying()
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''IsInPlayingNow()'''<br>''Checks the current file, and if in the Playing Now list, returns 1 (positive), and if not, returns 0 (negative).

<br>'''IsPlaying()'''
<br>''Checks the current file, and if currently playing, returns 1 (positive), and if not, returns 0 (negative).
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''if(isinplayingnow(),Selected,Not Selected)'''<br>''As mentioned in the description, the ideal place for these functions is as 'expression columns'. If this example were used in an expression column, then files added to Playing Now will show as "Selected" and all other files would show as "Not Selected". If the idea here is to be able to quickly see which files have been added, this might look a bit 'busy' and defeat the purpose, to which end, it is perfectly acceptable to tell the expression that if a file is not in Playing Now, to output nothing, by simply not giving any instructions for the negative result, like so: '''if(isinplayingnow(),Selected,)'''. Now, this expression column will only show "Selected" against files that are in Playing Now, leaving all others empty, giving a much easier column to read.

<br>Use'' IsPlaying ''in exactly the same way as IsInPlayingNow()''

<br>''On the Interact support forum,'' '''[http://yabb.jriver.com/interact/index.php?topic=57461.0 mark_h describes how he puts these two functions to work for him]''', ''and rick.ca shows how he tweaked the idea when he answers the question:'' '''"[http://yabb.jriver.com/interact/index.php?topic=58137.msg393905#msg393905 is it possible to play an artist's full work when a genre is shuffling?]"'''
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
<br><br>
===Change how existing data is displayed using Format functions===
All of these functions (with the exception of FormatBoolean) take raw data from the library and allow us to present that data in a way that we choose. What does "raw data" mean? MEDIA CENTER stores duration information in seconds and converts that information into hours (if needed), minutes and seconds for display in the Duration column in a file list. Likewise, file size information is stored in bytes and is converted into Mb for display in the file list. Dates are stored using a UNIX system (use google if you want to know more about that) which means that the date field could contain 40121.8272916666683159 and MEDIA CENTER will display that as 04/11/2009 19:51 (if that is how your Windows locale setting displays date and time). So there you have it, raw data. The following section gives some idea of what is possible using the raw data and the Format functions. '''''To&nbsp;instruct the expression evaluator to use raw data, a zero is added to the library field, inside the square brackets, like so: [Date Imported,0]'''''
====FormatDate(...): Formats a date value in a specified manner====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FormatDate()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | As mentioned in the [[#Change how existing data is displayed using Format functions|section introduction above]], MEDIA CENTER stores date information in a UNIX style, and converts that information into legible date/time information we can understand. By default, MEDIA CENTER presents dates using the system locale settings. This function can be applied to any default library field that contains date information in order to have that information displayed in a non-default format.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''formatdate([date field,0],Format,Output if date is empty)'''

''Available format choices:''

* Year ''Returns the full year, i.e. 2010''
* Month ''Returns the full month, i.e. April, November.''
* Day ''Returns the day in number format, i.e. 23 (note that single numbers have no leading zero)''
* Filename ''Returns a filename friendly date format that also includes the seconds&nbsp;information to help avoid file names clashing, i.e. 20040521-032221''
* Elapsed ''Returns "how long ago" information, i.e. 2.43 Days or 1.85 Years''
* DateTime ''Returns the date and time using the system format on the machine running the expression.''
* hour ''Returns the hour from dates with time information. (note that single numbers have no leading zero)''
* minute ''Returns minutes from dates with time information. (note that single numbers have no leading zero)''

''Flexible formatting is also available: ('''Note that these <ins>are case sensitive</ins>)'''''

* yy ''Returns the last two digits of the year''
* yyyy ''Returns the full year''
* MM ''Returns the month as two digits''
* MMM ''Returns the month as three letter abbreviations''
* MMMM ''Returns the month in full''
* dd ''Returns the day as two digits''
* ddd ''Returns the day as three letter abbreviations''
* dddd ''Returns the full day''

Output if date is empty: ''If the date is empty, anything placed here will be output instead. This could be plain text, such as "No Date", or a library field. This value is optional, and if not given, the expression will default to return nothing if the date is empty.''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''formatdate([last played,0],yyyy//MM//dd,Not Yet)'''<br>''This will return the last played date as year/month/day without the time, and regardless of the system locale setting. If a file has no last played info, the expression will output "Not&nbsp;Yet" instead.''

<br>'''formatdate([date imported,0],month)'''
<br>''This will return the month a file was imported, written in full. For example, December, as opposed to 12.

<br>'''formatdate([date imported,0],month)&datatype=[month]'''
<br>''If you were to use the previous expression to create a view category that contained the months your files were imported, it would list the months alphabetically, with April first and September last. Thankfully, we can specify "data types" for expressions which further fine tune how MEDIA CENTER displays the results. In this case, a data type of month has been specified, therefore MEDIA CENTER will list the months in the correct chronological order. Data types are discussed [[#Specify data types for expression based fields|further down this page]].
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====FormatNumber(...): Formats a number to a specified number of decimal places====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FormatNumber()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | '''FormatNumber()''' allows to format any given value to a set number of decimal places.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''FormatNumber(Value to format,Number of decimal places,Output if value is zero,Label if value is greater than 1,Label if value equals 1)'''

* "Value to format" ''This could be a library field, such as [replay gain] or the result of a [[#Math()|Math()]] expression. Any numerical value you encounter where you would like to limit the number of decimal places displayed can have this function applied.''
* "Number of decimal places" ''This is optional. If not specified, the function will default to zero decimal places. Use -1 to output as many decimal places as necessary.''
* "Output if value is zero" ''This is optional. If not specified, the function will return zero.''
* "Label if value is greater than 1" ''This is optional. If not specified, the function will not return anything, if specified, and the formatted number is greater than 1, the function will return with the number, plus this label.''
* "Label if value equals 1" ''This is optional, as detailed below..''
** If not specified, but a label for greater than 1 has been specified, then this "greater than 1" label will always be used.
** If neither are specified, the function will not return anything.
** If both are specified, and the formatted number equals 1, the function will return with the number, plus this label.''

''Note that even if you are only interested in applying a label for those results that equal 1, you must also indicate the preceding instructions, if only to instruct the evaluator to ignore them, as shown in the examples below.''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''formatnumber([duration,0],2)'''<br>''This will return the duration of a track, in seconds, shown to two decimal places.''

<br>'''formatnumber([number plays,0],0,Not played this one yet,Plays,Play)'''
* "0" decimal places has been specified, therefore the result will be a whole number with no decimals shown.
* ''If [number plays] is zero, the result will be "Not played this one yet"''
* ''If [number plays] is greater than 1, lets say 6, the result will be "6 Plays"''
* ''If [number plays] is 1, the result will be "1 Play"''

<br>'''formatnumber([number plays,0],,,,Time)'''
''Here, the function will fall back to its defaults for everything except when the number equals one:''
* ''No decimal places have been specified, the result will default to a whole number with no decimals shown.''
* ''If [number plays] is zero, the result will be "0"''
* ''If [number plays] is greater than 1, lets say 6, the result will be "6"''
* ''If [number plays] is 1, the result will be "1 Time"''
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====FormatDuration(...): Presents a duration of seconds in a reader friendly format====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FormatDuration()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | MEDIA CENTER stores duration data in seconds, at up to sixteen decimal places. The value shown in the default "Duration" column in a file list is an internally formatted interpretation of this raw "Duration" data. As MEDIA CENTER automatically applies this formatting for us, there is not a lot of call for this particular function.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''FormatDuration(Value to format)'''

''"Value to format" can be either the raw duration data, or a given number of seconds''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''formatduration([duration,0])'''<br>''This expression will duplicate the contents of the default [duration] field as shown in a file list''

<br>'''formatduration(600)'''
<br>''This will output ten minutes in the format 10:00''
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====FormatFileSize(...): Presents a number of bytes in a reader friendly format====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FormatFilesize()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | MEDIA CENTER stores file size data internally in bytes. This function will convert those byte values into reader-friendly values, 3.2 Kb or 10.4 Mb, for example. The function will also accept a byte value directly.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''FormatFileSize(Value to format)'''

''"Value to format" can be either the raw [File Size] data or a given number of bytes.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''formatfilesize([file size,0])'''<br>''This expression will duplicate the contents of the default [file size] field as shown in a file list''

<br>'''formatfilesize(56123456)'''
<br>''This expression will convert 56,123,456 bytes and the output will be 53.5 MB''
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====FormatRange(...): Formats a value as a range====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FormatRange()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function places any given value into its place in any given range.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''FormatRange(Value to format,Range size,Mode)'''
'''Value to format:''' ''This could be a specific word or number, or any library field''
<br>'''Range Size:''' ''A numerical value dependent on how you wish to set up your range. If not specified, this will default to 1''
<br>'''Mode:''' ''There are three possible modes, detailed below. If not specified, this will default to zero.''
* '''0:''' ''Automatically choose between number / letter grouping''
* '''1:''' ''Specifies that letter grouping should be used''
* '''2:''' ''Specifies that number grouping should be used''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''formatrange([artist])'''<br>''This will return the first letter from the [artist] field. Note that as '''range size''' and '''mode''' values were not specified, the function defaulted to one and automatic respectively.''

<br>'''formatrange([artist],3,1)'''<br>''This will take the first letter from the artist field and place it in the appropriate letter range. In this case, a range size of three has been specified, therefore the output will be in the form of "a-c", "d-f", "g-i" etc. etc.''

<br>'''formatrange([bitrate],100,2)'''<br>''This will take the bitrate and place it in the appropriate number range. In this case a range of 100 has been specified, therefore the output will be in the form of "0-99", "100-199", "200-299" etc. etc.''

Note that this function always starts number ranges from zero, 0-9, 10-19, etc, etc.. If you really need a number grouping that starts from 1, 1-10, 11-20, 21-30,etc. etc., you can use expressions to create a pseudo range. Full details, with a helpful explanation, of "1 based grouping" can be found [[CD_Reference_Number|on this page]].
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>

====FormatBoolean(...): Formats a boolean (true / false) value in a specified manner====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FormatBoolean()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function is wrapped around another function and will return specified strings for true and false values returned by that other function.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''FormatBoolean(True/False Test,String to use if true,String to use if false)'''
* '''True/False Test''' ''Other functions perform their respective tests and return 1 to indicate a true result, and 0 to indicate a false result''
* '''String to use if true,String to use if false''' ''If these are not specified, the function will default to using "True" and "False"''

|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''formatboolean(isempty([number plays]),Never Played,Has Been Played)'''<br>''On it's own, the function'' isempty([number plays]) ''will return either 1 or 0. When wrapped inside a'' formatboolean ''function as shown here, the output for a true result will be "Never Played", and for a false result, the output will be "Has Been Played".

<br>'''formatboolean(isempty([number plays]))'''<br>''Here, there are no strings specified for the true/false results, therefore the function will default to using "True" and "False"''
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
<br><br>
===Functions for filename and field manipulation===
The primary use of the functions in this section is to manipulate the data associated with any given file or files. When used with direct editing in the file list, or in the action window, as decribed [[#When, Where and How to use expressions|further down this page]], they offer extremely fast and efficient methods for batch editing the actual tag data associated with multiple files.<br>Note that when used indirectly, in expression based columns, categories or library fields, the referred fields are not altered in any way, the data is merely presented in the expression field formatted as requested.
====Clean(...): Returns a cleaned up version of a filled in template====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Clean()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | The official description for this function is simply "Returns a cleaned up version of a filled in template". This function is better explained through demonstration in the examples below.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''Clean(template to clean)'''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''Clean([Artist] - [Album] /([Genre]/))'''
* First of all, note that this example uses the "forward slash" escaping, as discussed in the [[#Overview|Expressions Overview]] earlier. The result here will be that the [Genre] will be returned wrapped in parenthesis. Without the escaping, the function would fail as the evaluator attempts to read the parenthesis as an integral part of the expression.

* Imagine the template without the Clean() function around it. ''[Artist] - [Album] /([Genre]/)''<br>If used as an expression, this string, quite predictably, will return things such as: "AC/DC - Back In Black (Rock)", but, what if one or more of the specified fields contains no data? The result would be rather untidy, such as: "- Back In Black ()" if there were no [artist] or [genre] data.<br>Wrap the template inside the Clean() function to tidy these cases up, so, "- Back In Black ()" would become "Back In Black"
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====FixCase(...): Changes the case of a given string====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FixCase()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function will output any given text string in one of five specified case modes.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''FixCase(String to modify,Case mode to apply)'''<br>''The ''"String to modify"'' can be plain text, a library field, or a combination of the two.''

The five modes available are:
* '''0:''' ''Title Case''
* '''1:''' ''All Words''
* '''2:''' ''First word''
* '''3:''' ''ALL UPPERCASE''
* '''4:''' ''all lowercase''

''If no case mode is specified, the function will default to using "Title Case". Title case will start each principal word with a capital. More detail regarding title case can be found [http://www.grammar-monster.com/lessons/capital_letters_title_case.htm here]''

|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''fixcase([album])'''<br>This will take the contents of the [album] field and present it with the specified capitalisation. As there is no specified mode here, the function defaults to 0, so, if an album is entered in the library as "Time Out Of Mind", the function will return "Time Out of Mind" (note the lower case "of")

<br>'''fixcase(MY ALbUm IS cAlLeD [album],4)'''<br>This would return "my album is called time out of mind"
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====Length(...): Returns the number of characters in a string====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Length()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function returns the number of characters in any given string.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''Length(String to count characters from)'''<br>''The ''"String to count characters from"'' can be plain text, a library field, or a combination of the two.''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''length([filename])'''<br>''This will count the characters in the [filename] field and return the result. Spaces count as characters, so, C:\My File.mp3 would return 14.

<br>'''if(isequal(length([filename]),68,6),68 Characters or more,Less than 68 Characters)'''<br>''Here, Length() has been combined with another two functions, "If()" and "IsEqual()". The expression compares the length of the filename against the number 68. If there are 68 or more characters in the filename, the expression will return "68 Characters or more", otherwise, it will return "Less than 68 Characters". If you are working with a device with filename length limitations, these functions can be used to create extremely useful expressions that could help with your device management.''
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====Left(...): Retrieves a specified number of characters from the left of a value====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Left()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function retrieves a specified number of characters from the left of any given value.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''Left(Value to get characters from,Number of characters to get)'''<br>''"Value to get characters from" can be plain text, a library field, or combination of both. If more characters than exist are requested, all available characters are returned.''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''left([filename],3)'''<br>''This will return the drive letter, colon and first back-slash from the filename. If asked to show more characters than actually exist, the expression will return the entire value, also, remember that spaces count as characters too.''
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====Right(...): Retrieves a specified number of characters from the right of a value====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Right()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function retrieves a specified number of characters from the right of any given value.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''Right(Value to get characters from,Number of characters to get)'''<br>''"Value to get characters from" can be plain text, a library field, or combination of both. If more characters than exist are requested, all available characters are returned.''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''right([filename],3)'''<br>''This will return the last three characters from the filename. If asked to show more characters than actually exist, the expression will return the entire value, also, remember that spaces count as characters too.''
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====RemoveLeft(...): Trims characters from the start of a value====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | RemoveLeft()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | The output from this function will remove a specified number of characters from the start of any given value.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''RemoveLeft(Value to remove characters from,Number of characters to remove)'''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''removeleft([name],5)'''<br>''This would show the name field, with the first five characters removed. If asked to remove more characters than actually exist, the output will be blank, also, remember that spaces count as characters too.''.
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====RemoveRight(...): Trims characters from the start of a value====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | RemoveRight()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | The output from this function will remove a specified number of characters from the end of any given value.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''RemoveRight(Value to remove characters from,Number of characters to remove)'''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''removeright([name],5)'''<br>''This would show the name field, with the last five characters removed. If asked to remove more characters than actually exist, the output will be blank, also, remember that spaces count as characters too.''.
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====Mid(...): Retrieves specified characters from a value.====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Mid()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Mid() retrieves a specified number of characters from a specified starting point in any given string.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''Mid(Value to get characters from,Character to start at,Number of characters to get)'''
* '''Value to get characters from''': ''This can be a library field, plain text, or a combination of both.
* '''Character to start at''': ''This is a numerical pointer, and rather confusingly, the function treats the first character as zero and begins from there. If not specified, the function will default to zero.
* '''Number of characters to get''': ''If this value is not specified, the function will default to 1. -1 can be used to retrieve all available characters after the specified start point.

|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''mid(12345)'''<br>''As values for "Character to start at" and "Number of characters to get" have not been specified, they default to 0 and 1 respectively and the function returns the first character in the string, 1.''

<br>'''mid(12345,1,2)'''<br>''The start point has been specified as the second character in, and 2 characters have been asked for, the result here will be 23.''

<br>An example of Mid() being used to re-order a date field was given in answer to the question "[http://yabb.jriver.com/interact/index.php?topic=52809.0 Can I include seconds in "import date"?]"
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====Replace(...): Replace or remove strings from a value.====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Replace()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Quite simply, this function allows to search for a specified string in a specified value, and if found, remove the specified string, or replace it with another.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''Replace(Value to check,String to check for,String to replace with)'''
* '''Value to check''': ''This can be plain text, a library field, or combination of both.
* '''String to check for''': ''Note that this check is <ins>case-sensitive</ins>''
* '''String to replace with''': ''Any instance of the "String to check for" will be replaced by this string. If not specified, any instance of the "String to check for" will be removed.''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''replace(My Sample String,S,Replaced )'''<br>''All instances of upper-case "S" will be replaced by the text "Replaced ", (note the trailing space), resulting in'' "My Replaced ample Replaced tring"

<br>'''replace(My Sample String,s,Replaced )'''<br>''The "Value to check" does not contain any lower-case "s", resulting in unchanged output, "My Sample String"''

<br>'''replace(My Sample String,/ Sample,stic)'''<br>''In this example, the space preceding the word Sample is to be included in the "String to check for". Remembering that, as discussed in the [[#Overview|Overview]], spaces that follow a comma are ignored unless escaped, an escaping forward slash is used to force the inclusion of the space in the check. The result here will be "Mystic String".
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====Counter(...): Counts upwards in specified increments====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | Counter()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function can be used to number objects sequentially, from a specified starting point, in specified increments. The counter resets itself to zero after five seconds of inactivity.<br>Counter() can exhibit a touch of wierdness when used in certain situations, will be covered in the examples, that demonstrate why this one is not really a 'fits all' function.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''Counter(Number to start counting from,Increments to count up in)'''

* '''Number to start counting from''': ''This is optional. If not specified, the counter will start from zero. If specified, the start value is inclusive, meaning that if a start value of five is specified, the first value the function returns will be five.''
* '''Increments to count up in''': ''This optional. If not specified, the counter will count up in increments of 1''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''counter()'''<br>This shows the function in its simplest form. The counter will start at zero and count upwards in increments of 1.

<br>'''[[#PadNumber(...): Used to add leading zeros to a number|padnumber]](counter(370,2),4)'''<br>This expression shows a combined use of functions. Counter() will count up, in two's, starting from 370, and the padnumber function will pad the results to four figures, giving output values of 0370, 0372, 0374, etc. etc..

<br>'''Weirdness'''<br>Counter() works really really well, and really really efficiently when used to sequentially number static data fields. It is not designed to be used in a dynamically changing expression column in a file list. To demonstrate this, right click on a list column header and choose the option to "Add expression column". Use the first, simple expression above, and press OK. The column is presented and all the items in the list are now numbered in this column, but, see what happens when you run the cursor up and down the list? The counter function just keeps on going and going. Right click on the expression column header, and it will appear at the top of the selectable columns list with a tick beside it, click on it to remove the column. This same anomally appears when counter() is used in the "Rename, Move and Copy Files" tool. There may be a possible solution to this effect as seen in the renaming tool by using the CustomData(#) function, but only if the count is to start from 1.<br>Some interesting reading regarding the use of Counter() can be found in answer to "[http://yabb.jriver.com/interact/index.php?topic=48659.0 how to fill the NAME field with incrementing numbers?]" and "[http://yabb.jriver.com/interact/index.php?topic=50622.0 Prepending a consecutive number to titles as I copy them from MC13 to mp3 player]".
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
<br><br>
===Functions for the manipulation and creation of list type fields===
The default MEDIA CENTER library contains many fields that are referred to as "list type" fields. Users are also able to add their own "list type" fields to their libraries. A list type field contains one or more text items seperated by semi-colons. The semi-colons are referred to as the 'delimiter' and when displayed in a view category, text items seperated by semi-colons are displayed in a list of seprately selectable items. The "Keywords" field is a classic example of a list type field, which demonstrates how list type fields allow a single file to be tagged with many different keywords, as opposed to a 'standard' field, such as 'Genre', where a single file can only be tagged with a single genre. The following functions provide the ability to combine or build custom list type fields using the default semi-colon delimiter, or a specified delimiter, count the number of items contained in a given list, or extract a numbered entry from within a list. Two of the functions listed in this section are used to create "list type" data from two or more existing sources and could reasonably be considered to be functions more suited to those who are very familiar with MEDIA CENTER and how it gets its job done. If these functions are used to create a new 'calculated data' library field, they will not function as 'list type' fields unless the field is first created as a "User Data" field, with "List Type" specified. After creating the field in this way, it is possible to go back and edit the field, changing it to "calculated data" and entering an expression to be used. The [http://yabb.jriver.com/interact/index.php?topic=54226.msg374211#msg374211 "Eureka moment"] occurred in November 2009.
====ListBuild(...): Build a list from a series of values====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | ListBuild()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | This function provides the ability to create a single list from many different sources and allows a list delimiter to be specified. It has two modes that can be applied and are detailed below. Of these two modes, mode "0" (Combine all values) should be avoided. It has been included for 'function completeness' only, and when used, can produce some very strange results that do not filter as expected.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''ListBuild(Mode,Delimiter,Items,To,Include)'''<br>
'''Mode:''' ''There are two different modes available:
* '''0''': ''combine all values. NOTE: <ins>This mode should be avoided as there is no recorded practical use for it, and it's behaviour can be unpredictable.</ins>''
* '''1''': ''combine non-empty values''

'''Delimiter''': ''The character used here will be used as a delimiter between each of the specified list items. To be clear, the keywords field uses a semi-colon delimiter by default; if a list is built using keywords and genre, and the specified delimiter is a back slash, it will be used between the keywords and genre fields when joining them, the semi-colons in the keywords field would not be altered. For example, if [keywords] contained "these;are;keywords" and [genre] contained "Rock", and these two were joined using ListBuild with a "\" specified as the delimiter, the resulting data would be "These;are;keywords\Rock". The real beauty and power of this function can be released when expressions are nested into the ListBuild instructions. For example, "listbuild(1,\,replace([keywords],;,\),[genre]" would return the data "These\are\keywords\Rock"''
<br>'''Items To Include''': ''This can be any number of specified text entries, expressions, or library fields, seperated by commas''
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''listbuild(1,;,[keywords],[genre])&datatype=[list]'''<br>''This will return a semi-colon delimited list containing all keywords and genres. If either keyords or genre is empty, they will be ignored, so, the data returned for a file with no keywords, and a genre of "Rock" would be simply "Rock".''

<br>'''listbuild(1,\,[genre],[album artist (auto)],[album])&datatype=[list]'''<br>''When MEDIA CENTER encounters a back slash character in a list type field, it 'nests' the data in the list. Think of this in exactly the same way as Windows reads file paths, each back slash is another folder along the file path, and in a MEDIA CENTER list type view category, each back slash creates a virtual folder, and each semi-colon starts a new list entry, which means that effective browsing trees can be created using this knowledge. In the example shown here, a list of genres would be created, and each genre is able to be expanded to reveal a list of artists, which in turn can be expanded to reveal albums by that particular artist in that genre. So, now that this is getting interesting, there's an issue with this example. If a file has no specified [genre], the value is ignored, and the [album artist (auto)] value is placed on the root of the virtual tree, which means that the completely collapsed list contains a mixture of [genre] and [album artist (auto)]. The next example demonstrates how to clean that up.''

<br>'''listbuild(1,\,if([[#IsEmpty(...): Tests to see if a field is empty|isempty]]([genre]),!No Genre Applied,[genre]),[album artist (auto)],[album])&datatype=[list]'''<br>''Here, the previous example has been improved by nesting an [[#IsEmpty(...): Tests to see if a field is empty|IsEmpty()]] function into the listbuild function. The result is that all files without a specified genre are placed in a group at the top of the virtual tree called "!No Genre Applied", and the rest of the root consists of existing genre values, which is much tidier.
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
====ListCombine(...): Combines two delimited lists into a single delimited list====
{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | ListCombine()
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | Unlike the [[#ListBuild(...): Build a list from a series of values|ListBuild]] function above, which can be used to create a list from any number of varying sources, ListCombine() is used to merge two specified lists into one.
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''ListCombine(First list,Second list,Input Delimiter,Output Delimiter)'''<br>

|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''EXAMPLES'''
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
===Now(): Retrieve and display the system date===
===Specify data types for expression based fields===
==When, Where and How to use expressions==



{| style="width: 100%; border: 1px solid black" align="top" border="1" cellpadding="3"
|- valign="top"
! scope="row" style="white-space:nowrap; background: #A8E4A0; color: black; border: 1px solid black;" width=100 | FUNCTION NAME
| style="background: #ecfeea; color: black; border: 1px solid black" width=1200 | FUNCTION DESCRIPTION
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Construction
| style="background: #ecfeea; color: black; border: 1px solid black" | '''FUNCTION CONSTRUCTION'''
|- valign="top"
|- valign="top"
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
! scope="row" style="background: #A8E4A0; color: black; border: 1px solid black;" | Examples
|style="background: #ecfeea; color: black; border: 1px solid black" | '''EXAMPLES'''
|style="background: #ecfeea; color: black; border: 1px solid black" | '''listcount([People])'''<br>
''No delimiter has been specified here, therefore the function will default to using a semi-colon. The result here will match the number of people shown in a properly tagged photo. Note that the function is smart, so, if a file has no [People] tag, the function will return zero (0), and if it has [People] data, but no semi-colon, the function will return one (1).''
|}
|}
<div style="text-align:right;">([[#top|Back to top)]]</div>
<div style="text-align:right;">([[#top|Back to top)]]</div>

Revision as of 16:22, 20 September 2010

ListCount(...): Returns the number of items in a delimited list

ListCount() ListCount is used to return the number of items that exist in any given field, using any given delimiter.
Construction ListCount(Field to count,Delimiter to use)

Field to count: Typically, this will be a list type field, but this is not compulsory. The data in any field can be parsed using any chosen delimiter

Delimiter to use: This is optional. If not specified, the function will default to using a semi-colon delimiter. Anything can be specified as a delimiter, from a single character to a whole word or words.

Examples listcount([People])

No delimiter has been specified here, therefore the function will default to using a semi-colon. The result here will match the number of people shown in a properly tagged photo. Note that the function is smart, so, if a file has no [People] tag, the function will return zero (0), and if it has [People] data, but no semi-colon, the function will return one (1).

(Back to top)