Specifics of value formatting
By default, 1C:Enterprise 8 converts Date and Number values to string format according to regional settings. The default regional settings depend on language (country) settings specified during infobase creation. You can change infobase language (country) in Designer (on the Administration menu, click Infobase regional settings). This dialog box also allows you to specify parameters for displaying dates, numbers, and Boolean values. For example, you can remove triplet separators from long numbers in a specific infobase.
The standard English(US) number presentation includes separating triplets by commas and using period as a decimal point character.
Note that the same rule is applied to conversion of all numbers to string format, regardless of number meaning. This is because the number only stores its absolute value and sign, and does not store any data related to its meaning. Therefore, numeric catalog codes and the like are formatted just like any other number, with triplets separated. You can also note that only the significant figures of the fractional part are displayed, regardless of the number of digits allocated for the number (for example, in a document attribute). In other words, a number itself does not contain information about the number of digits in it, and therefore is converted to string format according to the common rule. To display a number in string format with specific fomatting, use the Format() function or specify the format string in object properties (for example, in spreadsheet document cell properties).
If you specify space as triplet separator, the platform converts it to a nonbreaking space. This ensures that numbers in string format are never carried over to the next line. For example, if an agreement includes the total amount, the number must not be carried over in the print layout. You can get the nonbreaking space character from the Chars system value set using the following syntax: (Chars.NBSp).
Analyzing value types
1C:Enterprise uses values of Type type for analyzing value types. You can get a Type value from a string (type name) using the Type() function, or you can get a Type value from a value whose type you want to know using the TypeOf() function.
Use Type values for analyzing types. Example:
TypeOf(CurrentDate) = Type("Date");
Note that string presentations of types (Type values converted to strings) are intended for displaying to end users. For example, string presentations are displayed when a user selects a type in an input field. String presentations depend on the application interface language. Therefore, they cannot be used for analyzing types.
If you need to know the metadata object used as a basis for creation of a specific applied object, use the FindByType() method of ConfigurationMetadataObject.
For example, the following script fragment checks whether a value type is one of the catalogs.
Type = TypeOf(Constants.MainWarehouse.Get()); Md = Metadata.FindByType(Type); Message(Metadata.Catalogs.Index(Md) > 0);
You can use the AllRefsType() method of applied object managers to analyze applied object references. The method returns a TypeDescription object that contains object reference types. For example, the following script fragment checks whether a constant value is a catalog reference.
Type = TypeOf(Constants.MainWarehouse.Get()); Message(Catalogs.AllRefsType().ContainsType(Type));
Using time periods and points in time
In 1C:Enterprise dates include time with an accuracy up to one second. If you do not specify time explicitly, it is set to 00:00:00. A date difference is expressed in seconds. For example, if you specify a period between 01/01/2012 and 01/31/2012, it means a period from the first second of 01/01/2012 till the first second of 01/31/2012. Therefore, it does not include January 31, except the first second of this day. If you want to specify a full month period, set the boundaries from 01/01/2012 00:00:00 to 01/31/2012 23:59:59. Note that boundaries from 01/01/2012 to 02/01/2012 do not describe a full month period because the first second of February 1, 2012 is included.
Normally, users enter period boundaries as dates without time. When a user enters a period between 01/01/2012 and 01/31/2012, they mean the entire month. If you pass these values to system functions or queries, they will be interpreted as a period from 01/01/2012 00:00:00 to 01/31/2012 00:00:00. Therefore, you have to convert the end of period to the end of day. You can use the EndOfDay() function for this purpose. It returns the date with time set to the last second of the specified day. For example, Date(2012, 1, 31, 23, 59 ,59) and EndOfDay(Date(2011, 1, 31) give the same result.
Turnovers = AccumulationRegisters.CompanyFunds.Turnovers(Date(2012, 1, 1), EndOfDay(Date(2012, 1, 31)));
1C:Enterprise allows specifying date and time together with a related document. The PointInTime object stores both a date and a related document; it consists of a date and a reference to the recorder. The date of the point in time might not match the document date because documents can write register records for any period, not just for periods matching the document dates. To get the point in time that includes the document date and the document itself, use the PointInTime method of the document. For example, if you want to calculate document balance, passing a reference to the document to a method that calculates balances is incorrect. You have to pass the PointInTime object; you can get it by using the PointInTime() method of the document reference or create it using the New operator.
Balance = AccumulationRegisters.CompanyFunds.Balance(DocumentRef.PointInTime());
Balances = AccumulationRegisters.CompanyFunds.Balances(New PointInTime(Document.Date, Document));
System functions and virtual tables use parameters of Date and PointInTime types for calculating balance and turnovers. Balance is calculated for a specific point in time. When a point in time is specified for balance calculation purposes, the point itself is excluded from calculations by default. If a point in time's date is 11/21/2012 12:00:00, balance is calculated until (but not including) this point in time.
For example, an accumulation register contains the following records:
|11/21/2012 11:59:59||Receipt #1||Income||Refrigerator||5|
|11/21/2012 12:00:00||Expense #1||Expense||Refrigerator||2|
|11/21/2012 12:00:00||Expense #2||Expense||Refrigerator||1|
The balance as of 11/21/2012 12:00:00 is 5 refrigerators. The balance as of 11/21/2012 12:00:01 is 2 refrigerators. To calculate the balance including the specified point in time, use the Boundary object. It allows you to specify whether you want to include the point in time in the calculation. In the previous example, the balance for the boundary that is set as date 11/21/2012 12:00:00 (inclusive) is 2 refrigerators. Both expense documents Expense #1 and Expense #2 are included in the calculation because the boundary is set using a value of Date type. If you set the boundary as a point in time that contains date 11/21/2012 12:00:00 and recorder Expense #1, Expense #2 is excluded from the calculation and the resulting balance is 3 refrigerators. The following figure shows boundary positions on the time axis:
Unlike balances, turnovers are calculated for periods that have two boundaries. By default, both boundaries have "inclusive" type. But the meaning of "inclusive" and "excusive" differs for beginning and ending boundaries. For ending boundaries, the meaning is the same as in balance calculation: if a boundary is specified using a date, "inclusive" means "the end of second", and "exclusive" means "the beginning of second". For beginning boundaries, the contrary is true: "inclusive" means "the beginning of second", and "exclusive" means "the end of second". The following figure shows inclusive and exclusive boundaries for the period from 11/21/2012 00:00:00 to 11/21/2012 23:59:59.
Specifics of TypeDescription object
The TypeDescription object describes which value types are allowed. It only makes sense in the appropriate context, and it is normally used for describing allowed values of an object that is capable of storing other values. For example, in a value table a TypeDescription object can describe allowed value types for each column.
Note that a TypeDescription object and a Type value are different entities. A Type value defines the type of a specific value, while a TypeDescription object defines the acceptable range of values for an entity that can store values.
In addition to the list of types, a TypeDescription object contains qualifiers for Date, String, and Number primitive types. The qualifiers allow setting additional restrictions to value ranges.
If a TypeDescription object contains multiple types, it implicitly includes Undefined type because Undefined is the default value for attributes of composite type. If a TypeDescription object contains a single type, the default value has that type.
Take this into account, for example, when using AllRefsType() methods. An AllRefsType() method does not return an array of reference types; it returns a TypeDescription object that describes available types. The AdjustValue() method of the TypeDescription object returned by the AllRefsType() method follows the logic for getting default values of composite types: if TypeDecription contains multiple types and the passed value does not match any of these types, AdjustValue() returns Undefined.
If a TypeDescription object does not contain any types, it is treated as if it can store any type and therefore executing the AllRefsType() method does not make sense.
Columns of query results might contain NULL values in addition to the source field types. Therefore, the type of a value table column retrieved by a query does not exactly match the source field type—it might have the NULL type added.
Serialization usage specifics
1C:Enteprise provides tools for serializing many value types (that is, converting them to a format that allows saving and restoring them). In 1C:Enterprise script documentation, serializable objects are described with the "Serializable" keyword.
Use serialization whenever you need to store or transfer values in the serialized format within a single infobase for any reason.
This section describes regular serialization (not XML serialization). XML serialization is intended for data exchange with other 1C:Enterprise infobases and third-party systems. The "Serializable" keyword in object descriptions is not related to XML serialization.
1C:Enterprise has several features that utilize serialization.
Saving values to files, restoring values from files
This feature includes the ValueToFile() and ValueFromFile() methods. It is mostly used for saving temporary values within a session or between sessions.
Saving values to ValueStorage objects
This feature is mostly used for recording values that do not have matching field types, such as pictures or binary data, to an infobase. A value recorded to a value storage can be compressed.
Storing user parameters between sessions
The platform uses this feature for saving report or data processor form settings. This feature also includes the SaveValue() and RestoreValue() methods. We recommend that you use these methods for saving user-specific settings. However, we recommend that you do not use these methods for saving important data because data saved this way is not included in infobase backups. Also, this data is only saved at the end of session and therefore can be lost in the event of abnormal session termination.
Saving values to strings, restoring values from strings
This feature includes the ValueToStringInternal() and ValueFromStringInternal() methods but we recommend that you do not use them because they were implemented for compatibility with previous platform versions. Instead, use the ValueStorage object for storing values to the database. To get a string ID of a reference value, use the UUID() method, which gets a unique reference identifier, and then convert the value it returns to a string.
If an attempt to restore a reference to an applied object is made after the corresponding metadata object is deleted, the restoration result is an Undefined value.
The 1C:Enterprise serialization format is proprietary. We recommend that you always use 1C:Enterprise tools and do not use third-party tools for restoring serialized values.
1C:Enterprise serialization uses internal identification of value types. Identification of applied object types is based in internal IDs that are stored in metadata, therefore serialized values cannot be restored in another infobase even if it has exactly the same metadata object names and properties.
Summing up what has been said, use serialization for storing and transferring values within a single 1C:Enterprise infobase. Do not use it for data exchange with other infobases or third-party systems.
Using string value presentations
1C:Enterprise supports string presentations of most values. A string presentation is an explicit or implicit conversion to a String value. You can perform explicit conversion using the String() function. The conversion is also performed in string expressions, such as:
"Test:" + CurrentDate()
The platform also converts values to strings before displaying them in the user interface. For example, it converts values displayed in the message window (by the Message() function), tabular section values, spreadsheet document values, and so on.
Note that the sole purpose of string conversion is getting a human-readable value presentation, which is then displayed to the end user. Each value type supports a conversion method defined in the system. The conversion takes into account infobase, user, and session parameters.
For example, conversion of numbers, dates, and Boolean values to strings takes into account regional infobase settings.
When a reference to a document is converted to string, the following data is used: document synonym in the end user's language and the platform interface language.
Some values, such as Undefined and Null, have empty string presentations ("").
Sometimes the value itself affects generation of string presentations. For example, a string presentation of a value list contains a limited number of values, and each value has limited length.
The basic string presentation usage rule is as follows: use string presentations for displaying values in the user interface and do not use them in business logic algorithms. That is, do not parse string presentations and do not generate any values based on string presentations in your algorithms. Use string presentations only for displaying values on screen or writing them to files for later viewing and printing.
Do not use string presentations for serialization (saving values in string format). Use other serialization tools, such as writing values in XML format. For more information, see Serialization usage specifics.
Do not use string presentations for analyzing values (except for analyzing and comparing string presentations). For example, check values of Data type by comparing them with values of Data type. To check a value type, get the type and compare it with a value of Type type obtained from the type name; do not use string presentations of the type or value for this purpose. For more information, see Analyzing value types.
There are exceptions from this rule. A string presentation of a String object exactly matches its content. The string presentation of a UUID obejct is used for generating a value of this type from a string.
Remember that getting string presentations of references to database objects takes some time. Performing many conversions might hinder the system performance. The same is true for getting string presentations of values that contain references to database objects (for example, value lists).
Also remember that string presentation of numbers, dates, and Boolean values depend on infobase regional settings. For example, Russian number presentation includes nonbreaking spaces as separators between character triplets. To get a string presentation in custom format, use the Format() function. For more information, see Formatting values.
Understanding "empty" values
There are no "empty" values in 1C:Enterprise 8.
The Undefined value (which has Undefined type) is available instead. It is mostly used as a default value for composite objects, such as attributes or value table columns. If an attribute can store values of multiple types, its default value is Undefined. You can assign the Undefined value to a composite attribute to indicate that it does not store any values of other available types. A variable declared in a module also has the Undefined type until it is assigned a value. Note that TypeDescription objects that contain multiple types implicitly include the Undefined type too (because they can have Undefined value). Therefore, Undefined means the absence of value of any other type.
The Null value (which has Null type) is also available. It indicates the absence of a value in a selection retrieved from a database. For example, if you perform left or right join operations, record fields that are not selected have Null values. Also, if an attribute of a hierarchical catalog is only required for regular items and not required for groups (as specified in metadata), it has the Null value for groups. Similarly, attributes available only for groups have Null values for regular items.
Note that both Undefined and Null values have types (which match their names) and are only used in situations described earlier in this article. Do not use them as "empty" values of any other types.
Most types have default values, which are automatically assigned to objects of those types, such as attributes or value table columns. For example, 0 for numbers; an empty string for strings; or the date reference point ('00010101') for dates.
For types that represent references to database objects, empty reference values are available. You can get them using the EmptyRef() method of the corresponding manager. They are used as default values for the corresponding types. Note that if an attribute has composite type that includes a "reference to database object" type, you can assign the Undefined value to the attribute or you can assign the corresponding empty reference value to it—these two values are different. Choose one of these values depending on your application logic.
For example, an attribute can have two reference type values and it is evident from other attribute values that it must store a value of certain type (one of these two), but the user has not yet chosen a specific reference. Then you might want to assign an empty reference value of the required type. This allows a user to enter a value of the required type in the input field. In another scenario, if other attribute values imply that this attribute should not be filled at all, assign the Undefined value to it.
1C:Enterprise 8 includes the "unfilled value" concept, which is used in various service features. For example, you can set the No Empty Values parameter of a register dimension to True, and then the platform will automatically check whether the dimension is filled during each write operation. You can also use the AutoMarkIncomplete property (to set automatic underlining of unfilled fields) and the AutoChoiceIncomplete property (to start automatic value selection in an unfilled field).
All of the fill checks are performed according to the same rules. A value is considered unfilled if it is equal to the default value for its type. For example, a zero number, an empty string, or an empty reference to a catalog item are considered unfilled values.
Note that the IsEmptyString() function does not check whether a string value is equal to the default value. It checks whether a string contains significant characters. Space, nonbreaking space, and a few more characters are considered insignificant.
Specifics of database string comparison
1C:Enterprise functionality consists of two parts: operations performed in computer memory (at client or at server) and operations performed using DMBS tools (these include queries, many global context methods, and many applied object methods).
Although 1C:Enterprise type system is almost identical to that of the database, there are some differences. In particular, there is an important difference in string comparison operations. In 1C:Enterprise script, string comparisons are case-sensitive. In database operations, they are case-insensitive.
Of course, to perform case-insensitive comparison using script tools you can convert both strings to all uppercase or all lowercase letters. For example:
- "F" = "f" returns false;
- Upper("F") = Upper("f") returns true.
When using queries or performing other database operations, remember that the comparison is case-insensitive.
This affects the numbering feature. Codes and numbers of applied objects (catalogs, documents, and so on) are case-insensitive because they are maintained by database tools. If you attempt to set a new object code that differs from an existing code only by character case, you get the exception "Number field value not unique!". Code and number prefixes are also case-insensitive. A user-friendly solution uses only capital characters in codes and numbers.
If your script contains an algorithm whose logic must be identical to the logic of a database operation (for example, a text search), you might want to convert all strings to uppercase letters in the script to ensure that the comparison is case-insensitive.