📜 ⬆️ ⬇️

Presentation of the program settings in 1C. One of the methods


Hello.
In this article I want to talk about my experience with the settings in 1C - their presentation and preservation. This method is especially relevant for external processing and reports that are either not tied to a specific configuration, or simply do not want to store their settings in any configuration objects. The proposed method does not contain any special technical discoveries, it just makes the application of standard solutions more portable and orderly - all the tedious and hard work can be done once, and then the resulting template can be used with minimal changes in all of its projects. The essence of the method is just that.

Browsing the Internet on various examples of programs on 1C (source), I often noted that the approach to working with settings in most cases is quite negligent. Standard subroutines ( SaveValue , RestoreValue ) are used everywhere in the code and are not grouped in any way. For each stored value, a separate identifier is created in the database (string parameter of the above subroutines), even if there are hundreds of such values. Particularly significant is the implementation of a dialog box with mass editing of setting values. Long call sequence ( Restore Value , Save Value ) when opening and closing such window, respectively. Such an approach is understandable in principle - first of all, developers focus on solving a specific task, there is no time, as always, and working with settings is perceived in the same way as working with ordinary arithmetic expressions — these calls are inserted into the code as needed. Of course, if the developer is not annoying, then who cares. However, in cases when a massive alteration occurs in the program, it is not just necessary to add a few dozen more values ​​to the settings (which is done in most cases), but also to delete something, to change values ​​for some parameters (type of values), yes and just resetting the values ​​of the parameters (for testing purposes, for example) - it becomes unrealistic to perform such actions with a bunch of individual parameters - it is easier to score and perform all testing in the head, and not under the debugger.

And what if only one time to create a tool for working with settings - universal and portable? So that it can be easily, without thinking about copying between their programs (well, naturally changing the actual set of specific parameters). Let's try ...

In the implementation, we will use the previously described technical technique of “ homemade OOP in 1C ”. Create a program settings storage as a separate class (if you need to somehow isolate groups of settings, the program can have several such storage classes). Standard calls ( Restore Value , Save Value ) will be used once per program, because the entire contents of our repository will be serialized to an XML format . Thus, it is possible to provide a representation of a branched structure, and not just a “flat set” of values ​​(by the type of INI files). In our example, however, we will consider the same “flat set” for simplification, since The structure of the set is of no importance.
')
For example, suppose we have the following set of parameters:
TitleType ofInitial value
Param1Number0
Param2Line""
Param3ReferenceLink.NomenClaturaUndefined
Param4BooleanLying
Param5dateUndefined

Conventionally, we consider only the simplest types so as not to be tied to any specific configurations. But we also consider the reference type (the Nomenclature Handbook is available in many typical configurations) in order to show the idea of ​​serialization into a string and recovery from a string of a more complex object.

The structure of the class fields will look like this:
 _()  =  ; .("ChangeInfo", ); //       .("ErrMsg", ""); //     //  ,    .("Set_1", ); //   1 .("Set_2", ); //   2 .("Set_3", ); //   3 .("Set_4", ); //   4 .("Set_5", ); //   5  ;  

As you can see, besides the directly targeted parameters, there are utility fields in the class as well. Target fields have a special agreement in the name - start with the prefix " Set_ ". This is necessary in order to automatically distinguish the target and service fields when traversing the fields of a structure (imitating an object of a class) in a loop. Outside, these changes in the names are not visible and the usual parameter names are used (without the “ Set_ ” prefix).

Now we give the complete code of this class:
Class SettingsPrograms
 //////////////////////////////////////////////////////////////////////////////// //    () //       // // : // . // : //    //  _()   =  ; .("ChangeInfo", ); //       .("ErrMsg", ""); //     //  ,    .("Set_1", ); //   1 .("Set_2", ); //   2 .("Set_3", ); //   3 .("Set_4", ); //   4 .("Set_5", ); //   5  ;  //    // // : // . // : // () -     //  _()   = _(); //    _SetDefAttr();  ;  //    -   // // : //  -    //  _()   //      . // // : //  -    //  _SetDefAttr()  .ErrMsg = ""; .Set_1 = 0; .Set_2 = ""; .Set_3 = ; .Set_4 = ; .Set_5 = ;  //     2   1. //     1  . // // : // 1 -    // 2 -      //  _Assign(1, 2)   (1 <> )  (2 <> )  (_IsEqual(1, 2) = )      1   (., "Set_") = 1  //      (  ) 1[.] = 2[.]  ; 1.ChangeInfo =    //      . // // : // 1 -    // 2 -      //  // ,   2   ,   //  1   -    //  _IsEqual(1, 2)   = ;  (1 <> )  (2 <> )   = ;     1   (., "Set_") = 1  //      (  )  . <> 2[.]   = ;    ;  =  ;    //      . // // : //  -    //  _GetErrorMsg()   .ErrMsg  //     . // // : //  -    // PrmName -   //  //   PrmName  ,      //  _GetPrm(, PrmName)   = ; .ErrMsg = "";   = ["Set_" + PrmName];  .ErrMsg = "_GetPrm:   : " + PrmName; ;    //     . // // : //  -    // PrmName -   // PrmVal -    //  _SetPrm(, PrmName, PrmVal)  .ErrMsg = "";   ["Set_" + PrmName] <> PrmVal  ["Set_" + PrmName] = PrmVal; .ChangeInfo =    .ErrMsg = "_SetPrm:   : " + PrmName;   //      (   ). // // : //  -    // PrmName -   //  //    PrmName  ,      //  _GetPrmStrVal(, PrmName)   = ; .ErrMsg = "";   = ["Set_" + PrmName]; //        PrmName = "1"  //   â„–1 ()  = (, "=0; =''")  PrmName = "2"  //   â„–2 ()  =   PrmName = "3"  //   â„–3 (.)  ()   = .   =    PrmName = "4"  //   â„–4 ()  = (, "=0; =1")  PrmName = "5"  //   â„–5 ()  = (, "=""yyyyMMddHHmmss""")   .ErrMsg = "_GetPrmStrVal:   : " + PrmName + " : " + ().; ;    //          // (       ). // // : //  -    // PrmName -   // StrPrmVal -      //  _SetPrmFromStrVal(, PrmName, StrPrmVal)  .ErrMsg = "";   = ; //        PrmName = "1"  //   â„–1 ()  = (StrPrmVal)  PrmName = "2"  //   â„–2 ()  = StrPrmVal  PrmName = "3"  //   â„–3 (.)  (StrPrmVal)   = ..(StrPrmVal);   ()   =     PrmName = "4"  //   â„–4 ()  = ((StrPrmVal))  PrmName = "5"  //   â„–5 ()  = (StrPrmVal) ; //    ["Set_" + PrmName] <>   ["Set_" + PrmName] = ; .ChangeInfo =    .ErrMsg = "_SetPrmFromStrVal:   : " + PrmName + " : " + ().;   //      //    // // : //  -    //  //     //  _GetChangeInfo()   .ChangeInfo  //       //     // // : //  -    // ChangeInfo -     //  _SetChangeInfo(, ChangeInfo)  .ChangeInfo = ChangeInfo  //    XML-,    XML. // // : //  -    // XML -    XML- //  // ,       -    //  _LoadSettingsFromXML(, XML)   = ; //      .ErrMsg = "";  XML <>    //   _SetDefAttr(); //   _settings = ;  = "";  XML.()   XML. = "settings"   (_settings = )  (XML. = XML.)  //      _settings =   //      _settings = ;  = "";     _settings  //       XML. = XML.  //      = XML.;  XML. = XML.   ( <> "")  (.("Set_" + ))  _SetPrmFromStrVal(, , XML.);   XML. = XML.   = ""    ; //    .ErrMsg = ""  .ChangeInfo = ; //     =  //      //    XML .ErrMsg = "_LoadSettingsFromXML: " + ().;   //    .ErrMsg = "_LoadSettingsFromXML:   "; ;    //    XML-,   XML. // // : //  -    // XML -    XML- //  // ,       -    //  _SaveSettingsToXML(, XML)   = ; //      .ErrMsg = "";  XML <>    //   XML.XML(); XML.("settings"); //      Item     (Item., "Set_") = 1   = (Item., 5);   <> ""  XML.(); XML.((_GetPrmStrVal(, ))); XML.() //    ; //   XML- XML.(); // settings  .ErrMsg = ""  .ChangeInfo = ; //     =  //      //    XML .ErrMsg = "_SaveSettingsToXML: " + ().;   //    .ErrMsg = "_SaveSettingsToXML:   "; ;    //    XML-,    XMLStr. // // : //  -    // XMLStr -   XML- //  // ,       -    //  _LoadSettingsFromXMLStr(, XMLStr)   = ; //      .ErrMsg = "";  (XMLStr <> )  (XMLStr <> "")   XML =  XML(); XML.(XMLStr); //     = _LoadSettingsFromXML(, XML);  //    XML .ErrMsg = "_LoadSettingsFromXMLStr: " + ().;   //    .ErrMsg = "_LoadSettingsFromXMLStr:   "; ;    //    XML-,   XMLStr. // // : //  -    // XMLStr - ,   XML- //  // ,       -    //  _SaveSettingsToXMLStr(, XMLStr)   = ; //      .ErrMsg = "";  XML =  XML(); XML.(); //     = _SaveSettingsToXML(, XML); //  XML-       XMLStr = XML.();   //    XML .ErrMsg = "_SaveSettingsToXMLStr: " + ().; ;    //    XML- FName. // // : //  -    // FName -    XML- //  // ,       -    //  _LoadSettingsFromFile(,  FName)   = ; //      .ErrMsg = "";  (FName <> )  (FName <> "")   XML =  XML(); XML.(FName); //     = _LoadSettingsFromXML(, XML);  //    XML .ErrMsg = "_LoadSettingsFromFile:" + ().;   //    .ErrMsg = "_LoadSettingsFromFile:   "; ;    //    XML-,   FName. // // : //  -    // FName -  ,   XML- //  // ,       -    //  _SaveSettingsToFile(,  FName)   = ; //      .ErrMsg = "";  (FName <> )  (FName <> "")   XML =  XML("windows-1251",,,, " "); XML =  XML(); XML.(FName, XML); //     = _SaveSettingsToXML(, XML); //   XML.();  //    XML .ErrMsg = "_SaveSettingsToFile: " + ().;   //    .ErrMsg = "_SaveSettingsToFile:   "; ;    


Naturally, to get and set the values ​​of the parameters, you need to use the subroutines " SetupProgram_GetPrm " and " SetupProgram_SetPrm ", respectively. It is simply not possible to assign values ​​to a structure element that imitates a class.

This is the functionality of the settings that is sufficient in my opinion. You can expand it with any subprograms at will.

Using this configuration store looks like this:
 //  -   " " .   //        . // // : // . //  () //     = _(); XMLStr = ("_");  XMLStr <>   _LoadSettingsFromXMLStr(, XMLStr) ;  //  -   " " .   //    . //   . // // : // . //  () //     _GetChangeInfo()  XMLStr = ""; _SaveSettingsToXMLStr(, XMLStr); ("_", XMLStr); ; _();  //  -   ""  . //     . // // : //  -   -  //  () ("1 = " + _GetPrm(, "1")); ("2 = " + _GetPrm(, "2")); ("3 = " + _GetPrm(, "3")); ("4 = " + _GetPrm(, "4")); ("5 = " + _GetPrm(, "5"));  

Now we will sort the code of the dialog box for editing the preset. For our demo parameter set, it will look something like this:



Place the appropriate controls on the form to display and edit the parameters. Let's create the details for the form - for each parameter it is separate, and we will tie control elements to them. We will already exchange data between the settings store (an object of the NastrProgr class) and these details.
The source code for this form module is as follows:
Module code FormNastroykaParametrov
 //////////////////////////////////////////////////////////////////////////////// //      ; //     //////////////////////////////////////////////////////////////////////////////// //    //  -   " " .   //        . // // : // . //  () //        = .1  //  -   ""  OK. //      . // // : //  -  //  ()  CheckInput()  .(.)   //////////////////////////////////////////////////////////////////////////////// //   //           . // // : //  // : // ,       -    //  CheckInput()  = ; ErrMsg = ""; //    -  // ******************************** //       ErrMsg = ""  //    ReadSettingsFromInterf(); //       =   (ErrMsg) ;    //     . // // : //  //  LoadSettingsToInterf()   <>   //   1 = _GetPrm(, "1"); 2 = _GetPrm(, "2"); 3 = _GetPrm(, "3"); 4 = _GetPrm(, "4"); 5 = _GetPrm(, "5");   //     . // // : //  //  ReadSettingsFromInterf()   <>   //   _SetPrm(, "1", 1); _SetPrm(, "2", 2);  (3)  _SetPrm(, "3", 3)  _SetPrm(, "3", ) ; _SetPrm(, "4", 4); _SetPrm(, "5", 5);   //////////////////////////////////////////////////////////////////////////////// //    //         //   . // // : //  -   . // : // ,        ,    //   //  SetMainSettingsDlg()   = ; //       <>   //     = ; //      LoadSettingsToInterf(); //    .() = .  //     =   ;    


( ):
 //  -   ""  . //      . // // : //  -   -  //  () //      = _(); _Assign(, ); _SetChangeInfo(, ); //      = .("", );  .SetMainSettingsDlg()  //     _IsEqual(, )  //      _Assign(, );  ; _()  

. . , . . , , :
  _()  _SetDefAttr()  _GetPrmStrVal(, PrmName)  _SetPrmFromStrVal(, PrmName, StrPrmVal) 

( 1 8.2) .

That's all. Good luck to all. .

Source: https://habr.com/ru/post/272455/


All Articles