COM օբյեկտների հետ աշխատելու երեք սյուներ. COM կապով աշխատելն ավելի հեշտ է, քան կարծում եք

) Ճիշտ է

Միևնույն ժամանակ, ես մեկ անգամ չէ, որ տեսել եմ, երբ նույնիսկ 10 կետին չհասած հրապարակումները պարզապես «թռցրեցին»։
Ինչու՞ դա տեղի ունեցավ: Հավանաբար այն պատճառով, որ ինչ-որ մեկին ակնհայտորեն դուր են եկել դրանք:


Սա այն է, ինչ ես ասում եմ, որ լավ կլիներ առանց վարկանիշային հոդվածը կարդալու հասկանալ, թե որքանով է դա ձեզ անհրաժեշտ, կամ գնահատել ոչ այնքան պարզունակ +/-։ Ինչ վերաբերում է այն, ինչ ինձ դուր եկավ, ես դա կուղղեի այսպես. այն շատ բան ստացավ այն պատճառով, որ աստղերը հավասարվեցին, և շատ մարդիկ հավաքվեցին կայքում և շատերը հավանեցին այն, դուք ինքներդ հասկանում եք, որ սա պատահականության հարց է, քանի որ. Հենց որ հոդվածը դուրս է գալիս գլխավոր էջից, այն կարելի է գտնել միայն խնդրանքով, և այդպիսով բոլոր անցնողներն քվեարկում են: Եվ, որքան հասկանում եմ, մշտական ​​մեկնաբանությունները = հոդվածի առաջմղումը թույլ է տալիս պահպանել այն գլխավոր էջում։
Հենց դա է պատճառը, որ նրանք խանութներ են դնում հանրային փողոցներում. ի վերջո, հաճախ կարևորը ոչ թե ապրանքների որակն ու համապատասխանությունն է, այլ տեղանքի երթևեկելիությունը, որոնք քայլում են, հաճախ գնում են մի բան, որը նրանք դեն են նետելու գործընթացի համար։ Սա վաղուց բոլորին հայտնի հիվանդություն է՝ գնումներից կախվածություն։ Կամ պարզապես հոսքի ավելացումը մեծացնում է ճիշտ գնորդի հավանականությունը:

Եվ դրական և բացասական կողմերը... - սա ընդամենը մի տեսակ «շնորհակալություն» է ծախսած ժամանակի և աշխատանքի համար


Նրանք. Արդյո՞ք մինուսը նաև «շնորհակալություն» է համարվում: Ես ուզում էի իմանալ ձեր կարծիքը, թե արդյոք այն պետք է օգտագործել նման դեպքերում, և որքանո՞վ են հետաքրքիր մյուսները: Պե՞տք է այն դնել, երբ հոդվածը վնասակար/վատ է, թե՞ երբ այն պարզապես անօգուտ/դատարկ է քեզ համար:
Իմ կարծիքով, հոդվածը կարծես վարկանիշի պարզ բարձրացում է, քանի որ.
1. Իմ նշած տեսակների հետ կապված խնդիրը հեղինակի կողմից ամբողջությամբ անտեսվել է, թեև նա այնքան էլ ծույլ չէր գրել մի փունջ մեկնաբանություններ:
2. Հոդվածում ակնհայտ անճշտություն կա՝ ասվում է, որ դա միակ ճանապարհն է

V82 = Նոր COMObject («V82.ComConnector»); Կոդ = AccountCOM.Code;


բայց ես հանգիստ անում եմ դա՝ օգտագործելով այսպես.

Հաշվետվություն (Base. Directories. Counterparties. Find By Name ("LLC"). Code);


և ամեն ինչ լավ է! Իսկ ես ընտրում եմ V82.ComConnector կապը
Ինչ-որ տեղ տարօրինակ է, որ հեղինակին բոլորովին չի հետաքրքրում, որ իր հոդվածում կան մատնանշված խնդիրները, բայց նա ոչ մի կերպ չի արձագանքում։
3. Բայց դեռ խնդիր կա, երբ հայտնվում է «Class does not exist» սխալը
4. Բայց խնդիր կա, երբ տեղադրվում է 8.2, իսկ հետո տեղադրվում է 8.1-ը. փորձեք փոխանակել OLE/COM-ի միջոցով ստանդարտ UT-BP փոխանակման հետ:
5. Կարո՞ղ եք նշել կայքի հիմնական մշակումը, որը թույլ է տալիս համընդհանուր միանալ OLE/COM-ի միջոցով, որպեսզի սկսնակները ժամանակ չկորցնեն, դուք գրեք նրանց համար: Ի դեպ, ինչ-ինչ պատճառներով նրա նկարը ձեր էկրանին է, ինչո՞ւ: Եվ արդյունքում՝ 2 խոսք ըստ էության, ևս 6-ը կուլիսներում։

Ընդհանրապես, ես ցեխ չեմ շպրտում, այլ մատնանշում եմ կոնկրետ բացեր, բայց զրոյական ռեակցիա կա։ Եթե ​​սա այն փորձն է, որը դուք կիսում եք, ապա այն ինչ-որ տեղ սխալ է և թերի:
Իմ միտքն այն է, որ եթե հեղինակը ցանկանար հավաքել բոլոր թերությունները, նա կարող էր գոնե լսել ուրիշների փորձը և ոչ թե դիպչել մեկնաբանություններին: Միանգամից մի իրավիճակ է ստեղծվում, երբ կարդացողը հեղինակից ավելին գիտի, նրան ասում են (երբեմն՝ սխալ), նա էլ հակադարձում է։ Արդյունքում ամբողջ տեղեկատվությունը ոչ թե հոդվածում է, այլ մեկնաբանություններում։ Զվարճալի՜ Սա հաճախ է պատահում, բայց պետք չէ կենտրոնանալ այն փաստի վրա, որ դու ամենալավն էիր ուզում. Ներառեք դա հոդվածում, և ոչ բոլորն են հետաքրքրված այս փոխհրաձգության մեջ:

1C տվյալների բազաների միջև տվյալների փոխանակման տարբերակներից մեկը COM կապի միջոցով փոխանակումն է:

Օգտագործելով COM կապը, դուք կարող եք միանալ 1C տվյալների բազայից մյուսին և կարդալ կամ գրել տվյալներ: Այս մեթոդը կարող է օգտագործվել ինչպես տվյալների բազաների հաճախորդ-սերվերի տարբերակներում, այնպես էլ ֆայլերի տվյալների բազաներում: Այս հոդվածում մենք կանդրադառնանք այս տեսակի կապի օրինակներին: Օրինակները օգտագործում են հարթակ 8.2:

1C հավելվածի համար կարող եք ստեղծել երկու տեսակի COM օբյեկտներ: Սա V82. ԴիմումԵվ V82.COM Միակցիչ. Դեպքում V82. ԴիմումԳործարկվել է 1C հավելվածի գրեթե ամբողջական պատճենը: օգտագործման դեպքում V82.COM ՄիակցիչԳործարկվել է սերվերի մի փոքր մաս:
Գործողության արագությունն այս դեպքում ավելի բարձր է, սակայն որոշ գործառույթներ կարող են հասանելի չլինել: Մասնավորապես, աշխատել ձևերի և ընդհանուր մոդուլների հետ, որոնց համար դրված չէ արտաքին կապերով աշխատելու հատկությունը։ Հիմնականում դուք պետք է օգտագործեք V82.COM Միակցիչև միայն ֆունկցիոնալության բացակայության դեպքում V82. Դիմում. Գործառնական արագության տարբերությունը կարող է հատկապես նկատելի լինել մեծածավալ տվյալների բազաներում:

Այսպիսով, եկեք սկսենք

  1. Եկեք ստեղծենք COM օբյեկտ
    • Համար V82. ԴիմումՄիացում = Նոր COMObject ("V82.Application");
    • Համար V82.COM ՄիակցիչՄիացում = Նոր COMObject ("V82.COMConnector");
  2. Եկեք ստեղծենք կապի տող
    • տվյալների բազայի սերվերային տարբերակի համար ConnectionString = "Srvr = " "ServerName" ";Ref = " "BaseName" ;
    • տվյալների բազայի ֆայլի տարբերակի համար ConnectionString = "File = " "PathKBase" "; Usr = Օգտվողի անուն; Pwd = Գաղտնաբառ";
  3. Միացում տվյալների բազայի հետՄիացման փորձ = Միացում: Միացում (ConnectionString); Exception Message = New MessageToUser; Հաղորդագրություն. Տեքստ = + ErrorDescription(); Հաղորդագրություն. Զեկուցել() ; Վերջ փորձը ;
  4. Անջատվում է տվյալների բազայիցՄիացում = Չսահմանված;

    Օբյեկտի համար V82. ԴիմումԱնհրաժեշտ է դադարեցնել կապը, հակառակ դեպքում կմնա թերի նիստ, որն այնուհետև պետք է ջնջվի ձեռքով: Դեպքում V82.COM Միակցիչկապն ինքնաբերաբար խզվում է, երբ ավարտվում է միացումը, և կա ևս մեկ փոքր կետ:

    Օգտատիրոջ համար, ում հետ կապն իրականացվում է, «Ծրագիրը փակելիս հաստատման հարցում» վանդակը պետք է անջատված լինի իր կարգավորումներում:

Հիմա եկեք հավաքենք ամբողջ ծածկագիրը

Միացում = Նոր COMObject ("V82.Application"); //Միացում = New COMObject ("V82.COMConnector"); ConnectionString = "Srvr = " "Server1C" ";Ref = " "MyBase" "; Usr = Petya; Pwd = 123"; //ConnectionString = "File = ""C:\MyBase""; Usr = Petya; Pwd = 123";Միացման փորձ = Միացում: Միացում (ConnectionString); Exception Message = New MessageToUser; Հաղորդագրություն. Տեքստ = «Չհաջողվեց միանալ տվյալների շտեմարանին»+ Նկարագրություն Սխալ() ; Հաղորդագրություն. Զեկուցել() ; Վերջ փորձը ; Միացում = Չսահմանված;

Միացման տեսակի համար V82. Դիմումմեթոդը օգտագործվում է COM օբյեկտի համար, որը ստեղծվել է սկզբում և համար V82.COM Միակցիչմեթոդը կիրառվում է կապի համար: Այնուհետև հարցումը մշակվում է ստանդարտ 1C գործիքների միջոցով: կոդում այն ​​ունի հետևյալ տեսքը.

Հարցում = Միացում: NewObject («Հայցում»); // Համար V82.COM Միակցիչ Հարցում = Միացում: NewObject («Հայցում»); // Համար V82. Դիմում Հայց. Տեքստ = «Ընտրել | Կազմակերպությունների պաշտոնները, օրենսգիրքը. | Կազմակերպությունների պաշտոններ.Անուն|ԻՑ | Կազմակերպությունների պաշտոններ AS կազմակերպությունների պաշտոններ»; Արդյունք = Հայց. Run(); Նմուշ = Արդյունք: Ընտրեք (); Հրաժեշտի ընտրություն: Next() Loop EndLoop ;

1C:Enterprise 8.3 տարբերակի համար ամեն ինչ մնում է անփոփոխ, բացառությամբ, որ COM օբյեկտներ ստեղծելիս պետք է օգտագործել «V83.COMConnector»կամ «V83.Application».

Տպել (Ctrl+P)

1C տվյալների բազաների միջև տվյալների փոխանակման տարբերակներից մեկը COM կապի միջոցով փոխանակումն է: Օգտագործելով COM կապը, դուք կարող եք միանալ 1C տվյալների բազայից մյուսին և կարդալ կամ գրել տվյալներ: Այս մեթոդը կարող է օգտագործվել ինչպես տվյալների բազաների հաճախորդ-սերվերի տարբերակներում, այնպես էլ ֆայլերի տվյալների բազաներում: Այս հոդվածը քննարկում է այս տեսակի կապերը 8.3 հարթակում

com կապ

Դուք կարող եք ստեղծել երկու տեսակի COM օբյեկտներ 1C հավելվածի համար: Սա օլե կապեր է V83. Դիմում և com կապեր V83.COM Միակցիչ . Դեպքում V83. ԴիմումԳործարկվել է 1C հավելվածի գրեթե ամբողջական պատճենը: Օգտագործման դեպքում V83.COM ՄիակցիչԳործարկվում է սերվերի մի փոքր մաս: Գործողության արագությունն այս դեպքում ավելի բարձր է, սակայն որոշ գործառույթներ կարող են հասանելի չլինել: Մասնավորապես, աշխատել ձևերի և ընդհանուր մոդուլների հետ, որոնց համար դրված չէ արտաքին կապերով աշխատելու հատկությունը։ Հիմնականում դուք պետք է օգտագործեք V83.COM Միակցիչև միայն ֆունկցիոնալության բացակայության դեպքում V83. Դիմում. Գործառնական արագության տարբերությունը կարող է հատկապես նկատելի լինել մեծածավալ տվյալների բազաներում: Օգտագործված 8.2 հարթակի համար V82.Application կամ V82.COMConnector

Ստեղծեք OLE կապ

Միացում = Նոր COMObject («V83.Application»);

Ստեղծեք COM կապ

Միացում = Նոր COMObject («V83.COMConnector»);

Միացման տող

//Հաճախորդ-սերվեր տարբերակի համար
Միացման տող= “Srvr = ““ServerName” “;Ref = “ “BaseName” ;
//Ֆայլի ռեժիմի տարբերակի համար.
Միացման տող= «Ֆայլ = «PathKBase» «; Usr = Օգտվողի անուն; Pwd = Գաղտնաբառ»;
Փորձ
Միացում = Միացում . Միացնել(ConnectionString) ;
Բացառություն
Հաղորդագրություն = New MessageToUser;
Հաղորդագրություն . Տեքստ = «Չհաջողվեց միանալ տվյալների բազային» + Նկարագրություն Սխալներ (); Հաղորդագրություն . Զեկուցել();
Վերջ փորձը ;

Անջատում

Միացում = Չսահմանված;
Օբյեկտի համար V83. ԴիմումԱնհրաժեշտ է դադարեցնել կապը, հակառակ դեպքում կմնա թերի նիստ, որն այնուհետև պետք է ջնջվի ձեռքով: Դեպքում V83.COM Միակցիչկապն ինքնաբերաբար խզվում է, երբ ավարտվում է միացումը, և կա ևս մեկ փոքր կետ: Օգտատիրոջ համար, ում հետ կապն իրականացվում է, «Ծրագիրը փակելիս հաստատման հարցում» վանդակը պետք է անջատված լինի իր կարգավորումներում:

NewObject() մեթոդը

Նոր օբյեկտ ստեղծելու համար կարող եք օգտագործել NewObject() մեթոդը, օրինակ՝

Համար V83.COM Միակցիչ

RequestCOM = Միացում. Նոր օբյեկտ ( «խնդրանք») ;
TableCOM = Միացում. Նոր օբյեկտ ( «Արժեքների աղյուսակ») ;
ArrayCOM = Միացում: NewObject («Զանգված»);

ViewCOM =Connection.NewObject

Համար V83. Դիմում

RequestOLE = Միացում. Նոր օբյեկտ (" հարցում») ;
TableOLE = Միացում: Նոր Օբյեկտ(«Արժեքների աղյուսակ») ;
ArrayOLE = Connection.NewObject(«Զանգված»);
ViewCOM =Connection.NewObject(«UniqueIdentifier», StringUID);

RequestCOM . Տեքստ =«ԸՆՏՐԵՔ
| Կազմակերպությունների պաշտոնները, օրենսգիրքը.
| Կազմակերպությունների պաշտոններ.Անուն
|ԻՑ | տեղեկատու.Կազմակերպությունների պաշտոնները
ԻՆՉՊԵՍ ԿԱԶՄԱԿԵՐՊՈՒԹՅՈՒՆՆԵՐԻ ՊԱՇՏՈՆՆԵՐԸ»;

Արդյունք = RequestCOM: Run();
Նմուշ = Արդյունք. Ընտրեք ();
Հրաժեշտի ընտրություն: Հաջորդը ()Ցիկլ
Վերջնական ցիկլ;
Կարող եք նաև օգտագործել կազմաձևման օբյեկտների կառավարիչները.
DirectoryCOM = Միացում: տեղեկատուներ. DirectoryName;
DocumentCOM = Միացում. Փաստաթղթեր. Փաստաթղթի անունը;
RegisterCOM = Միացում: Տեղեկատվական ռեգիստրներ. Գրանցման անունը;

COM կապի միջոցով թվարկումների ստացում և համեմատում

Կազմաձևում սահմանված թվային տարրերի արժեքները համեմատելու համար անհրաժեշտ է վերափոխել այդ տարրերը պարզունակ տեսակներից մեկի, որի համեմատությունը հեշտ է: Նման տիպերը կարող են լինել կամ թվային կամ լարային: Դուք կարող եք թվային տարրի արժեքը վերածել թվային տիպի հետևյալի.

Enum Նյութ = Connection.Directories.Directory1.FindByCode(1).Props1;

PossibleValues ​​= Enum Element.Metadata().Enum Values;

EnumerationElementNumber = PossibleValues.Index(PossibleValues.Find(Connection.XMLString(EnumerationElement)));

Եթե ​​EnumerationItemNumber = 0, ապա հաշվետվություն ( «Թվային արժեքը 1»);

ElseIfEnumerationItemNumber = 1 ՀետոՀաշվետվություն («EnumerationValue2»);

վերջԵթե;

Օբյեկտի առբերում COM-ի միջոցով նույնացուցիչի միջոցով

Կազմաձևման օբյեկտների կառավարիչների միջոցով մենք ստանում ենք com օբյեկտ, օրինակ.
DocumentCOM = Միացում. Փաստաթղթեր. Փաստաթղթի անունը;

Այնուհետև մենք ստանում ենք եզակի նույնացուցիչի տող.

StringUID =Connection.string ( DocumentCOM.UniqueIdentifier())

Նույնացուցիչ = Նոր U եզակի նույնացուցիչ (StringUID);
ՀԵՏ linkByIdentifier = Փաստաթղթեր[DocumentName].GetLink(Identifier);

Եթե ​​Ձեզ անհրաժեշտ է գտնել com օբյեկտ ըստ փաստաթղթի ըստ նույնացուցիչի, ապա դուք պետք է գրեք այսպես.

WidCOM = Connection.NewObject(«UniqueIdentifier», StringUID);
LinkByIdentifier = Connection.Documents[DocumentName].GetLink(WidCOM);

Ողջույն Խաբրաչաններ։

Այս հոդվածում ես ուզում եմ խոսել այն մասին, թե ինչպես է հաստատվել իմ կազմակերպությունում 1C պլատֆորմի հետ ինտեգրումը: Այն, ինչ ինձ դրդեց դա անել, այս թեմայի վերաբերյալ տեխնիկական տեղեկատվության գրեթե իսպառ բացակայությունն էր: Կարդալով տարբեր հոդվածներ և զեկույցներ 1C-ն ցանկացած տեղեկատվական համակարգի հետ կապելու թեմայով, դուք նորից ու նորից համոզվում եք, որ դրանք բոլորն էլ մարքեթինգային, ցուցադրական բնույթ են կրում և երբեք չեն տեխնիկական, արտացոլում են խնդիրը և դրա լուծման էությունը:

Ես զգուշացնում եմ ձեզ, որ այս մեթոդը ոչ մի կերպ չի հավակնում ունիվերսալ լինելուն: Քանի որ կան բազմաթիվ 1C կոնֆիգուրացիաներ, և նույնիսկ ավելի շատ տեղեկատվական համակարգեր, լեզուներ և հարթակներ, հնարավոր համակցությունների թիվը հսկայական է: Իմ նպատակն է ցույց տալ մեկ հնարավոր լուծում.


Ես ընտրել եմ Python-ը որպես լեզու, որը ինտեգրվելու է 1C-ի հետ: Այն շատ հարմար է գործընթացների ավտոմատացման համար: Դրան նպաստում է շարահյուսության մինիմալիզմը (կոդը շատ արագ է մուտքագրվում), հարուստ ստանդարտ գրադարանը (երրորդ կողմի մոդուլների ավելի քիչ կարիք), խաչաձև հարթակ. մեծ հավանականությամբ Linix OS-ով գրված կոդը հաջողությամբ կաշխատի Windows-ում։ .

Սկզբից ես ուրվագծեմ այն ​​տվյալները, որոնցով մենք աշխատելու ենք։ Կազմակերպությունը Հեռավոր Արևելքի տարածաշրջանում էներգիայի վաճառքով զբաղվող ընկերություն է. այն սպասարկում է մոտավորապես 400 հազար բաժանորդների, 1C տվյալների բազան հիմնված է հատուկ կոնֆիգուրացիայի վրա: Յուրաքանչյուր բաժանորդի համար պահվում են նրա վճարումները, վճարները, սպառված ծառայություններն ու հաշվարկային սխեմաները, հաշվիչները, ընթերցումները և շատ այլ տվյալներ։

Ժամանակին մի կազմակերպություն ուներ մի ծրագիր, որը գրված էր Դելֆիում և օգտագործում էր MSSQL/Firebird-ը որպես տվյալների բազա: Այդ փառահեղ ժամանակներում դուք կարող էիք միանալ տվյալների շտեմարանին՝ օգտագործելով ցանկացած լեզվով և կատարել բազմաթիվ գործողություններ՝ ընտրել պարտապան բաժանորդներին, փակցնել ստացված վճարումները, ձայնագրել գործիքների ընթերցումները: Զարմանալի չէ, որ առօրյան ավտոմատացնող սցենարների հավաքածուն անընդհատ աճում է։ Ծրագրավորողները կարող էին ցանկացած գործողություն կատարել առանց ծրագիրը բացելու:

Ափսոս, 1C-ին անցնելով, անվճարն ավարտվեց. այլևս հնարավոր չէր ուղղակիորեն միանալ տվյալների բազային: Ընդհանուր առմամբ, 1C հարթակն ինքնին անբաժանելի է և իրեն լավ չի տրամադրում այլ համակարգերի հետ ինտեգրվելու համար: Նա, ինչպես ասում են, ինքնին մի բան է։ Տվյալները 1C-ում բեռնելիս պետք է հիշել, որ այնտեղից հանելը այնքան էլ հեշտ չի լինի։ Բայց հաշվի առնելով այն հանգամանքը, որ կազմակերպությունը պետք է ներդրեր վճարային համակարգեր և անձնական հաշիվ, անհրաժեշտ էր ինչ-որ լուծում գտնել։

Իմ առջեւ ծառացած հիմնական խնդիրներն էին կոնկրետ անձնական հաշվի վերաբերյալ տվյալներ արագ ստանալու հնարավորությունը՝ լրիվ անվանումը, հասցեն, չափիչ սարքերը, գործիքների ընթերցումները, վճարումները, վճարները: Գումարած փաստաթղթերի ստեղծումը՝ հաշտության հաշվետվություն, վճարման անդորրագիր: Այսպիսով, տվյալների բազայի հետ ուղղակի կապի հնարավորություն չկա. յուրաքանչյուր ոք, ով դիտել է 1C տվյալների բազան SQL սերվերի վրա, տեսել է, որ դժվար է հասկանալ աղյուսակների զանգվածը, ինչպիսիք են aaa1, aaa2: Իսկ նման աղյուսակների և դաշտերի անուններով հարցումներ կառուցելն ուղղակի անիրատեսական է: Բացի այդ, շատ 1C աղյուսակներ (հատկապես ամենակարևորները, օրինակ՝ վերջինի մի հատվածը, մնացորդները և հեղափոխությունները) վիրտուալ են և ցրված են տարբեր ֆիզիկական աղյուսակների վրա՝ հավաքված բազմաթիվ միացումների միջոցով: Այս մեթոդը հարմար չէ:

1C հարթակն ապահովում է COM կապի միջոցով դրան միանալու հնարավորություն։ Ինչպես Windows-ի շատ ծրագրեր, 1C-ի տեղադրման ժամանակ համակարգում գրանցվում են երկու COM օբյեկտներ՝ Automation Server և COM Connector: Երկու օբյեկտների հետ էլ կարելի է աշխատել՝ օգտագործելով COM տեխնոլոգիան աջակցող լեզու:

Automation Server օբյեկտը 1C հավելված է, որը գրեթե չի տարբերվում սովորական հաճախորդի հավելվածից: Տարբերությունն այն է, որ հավելյալ հնարավոր է ծրագրային կերպով կառավարել հավելվածի օրինակը։ COM Connector օբյեկտի հետ աշխատելիս գործարկվում է 1C հավելվածի թեթև տարբերակը, որի ձևերը, ինչպես նաև ինտերֆեյսի և տեսողական էֆեկտների հետ կապված գործառույթներն ու մեթոդները հասանելի չեն: Հավելվածն ինքնին սկսվում է «Արտաքին կապ» ռեժիմում: Գլոբալ փոփոխականների սկզբնավորումը (օրինակ՝ ընթացիկ օգտագործողի և նրա կարգավորումների որոշումը) պետք է իրականացվի 1C արտաքին կապի մոդուլում: Եթե ​​արտաքին կապի ռեժիմում կոդը կանչում է մի ֆունկցիա, որը հասանելի չէ այս ռեժիմում, բացառություն կհայտնվի (որը կփոխանցվի մեր Python սկրիպտին): Անվտանգ գործառույթների զանգերը պետք է շրջանակված լինեն ձևի կառուցվածքներով

#Եթե ՈՉ OuterJoin Ապա Զգուշացում («Բարև!»); #TheEndIf

Քանի որ COM օբյեկտների հետ աշխատելը բացառապես Windows-ի համար նախատեսված տեխնոլոգիա է, զարմանալի չէ, որ այն ներառված չէ ստանդարտ Python բաշխման մեջ: Ձեզ անհրաժեշտ է տեղադրել ընդլայնում` մոդուլների մի շարք, որոնք ապահովում են բոլոր անհրաժեշտ ֆունկցիոնալությունը Windows-ի տակ Python-ում ծրագրավորման համար: Այն կարող է ներբեռնվել որպես նախապես կառուցված exe տեղադրող: Ընդլայնումը ինքնին ապահովում է մուտք դեպի ռեեստր, ծառայություններ, ODBC, COM օբյեկտներ և այլն: Որպես այլընտրանք, դուք կարող եք անմիջապես տեղադրել ActiveState Python բաշխումը, որը գալիս է առանց տուփի Win32 ընդլայնման:

Որոշ ժամանակ ես փորձեր էի անում COM կապով վեբ հավելվածներ մշակելու համար, մասնավորապես, անձնական հաշիվ: Բացահայտվել են հետևյալ թերությունները.

COM կապը դանդաղ է: Ցածր կատարումը COM տեխնոլոգիայի հայտնի թերությունն է:
- 1C-ի հետ կապ հաստատելու գործընթացը, կախված կոնֆիգուրացիայից, կարող է տևել 1-ից 8 վայրկյան (իմ դեպքում՝ 6 վայրկյան): Ավելորդ է ասել, որ յուրաքանչյուր հարցման համար կապ հաստատելը կհանգեցնի նրան, որ յուրաքանչյուր էջի բեռնումը տևում է 8 վայրկյան:
- Քանի որ Python-ում վեբ հավելվածներն աշխատում են որպես անկախ սերվերներ, նախորդ կետը կարելի է փոխհատուցել՝ կապը պահելով որոշ գլոբալ փոփոխականում և վերականգնելով այն սխալի դեպքում։ Անկեղծ ասած, ես դեռ չեմ մտածել, թե ինչպես կապ պահպանել PHP-ում:
- Վեբ հավելվածի միջպլատֆորմային ֆունկցիոնալությունը կորել է:

Ելնելով վերը թվարկված կետերից՝ որոշվեց փոխել փոխազդեցության սկզբունքը՝ այն բաժանելով 2 մասի. ունակ է աշխատել տվյալների հետ՝ առանց սկզբունքորեն որևէ կասկածելու 1C-ի մասին:

Գործողությունների ռազմավարությունը հետևյալն է. Python սկրիպտը միանում է 1C-ին, կատարում է անհրաժեշտ հարցումները և տվյալները վերբեռնում SQLite տվյալների բազա։ Դուք կարող եք միանալ այս տվյալների բազային Python-ից, PHP-ից, Java-ից: Մեր նախագծերի մեծ մասն աշխատում է Python-ում, և քանի որ ես չեմ կարողանում ձեռքով գրել հում SQL հարցումներ, SQLite տվյալների բազայի հետ ամբողջ աշխատանքը կատարվում է SQLAlchemy ORM-ի միջոցով: Այն ամենը, ինչ պահանջվում էր, տվյալների բազայի տվյալների կառուցվածքը դեկլարատիվ ոճով նկարագրելն էր.

sqlalchemy.ext.declarative import declarative_base-ից sqlalchemy import Column, Integer, Numeric, DateTime, Unicode, Boolean, LargeBinary, ForeignKey Base = declarative_base() դասի Abonent(Base). Ճիշտ է) հաշիվ = Column(Unicode(32), index=True) կոդը = Column(Unicode(32)) հասցե = Column(Unicode(512)) fio = Column(Unicode(256)) աղբյուր = Column(Unicode(16)) ) psu = Column(Unicode(256)) tso = Column(Unicode(256)) np = Column(Unicode(256)) փողոց = Column(Unicode(256)) տուն = Column(Integer) flat = Column(Integer) mro = Column(Unicode(256)) դաս Վճարում(Base): __tablename__ = "payments" # և այլն...

Այժմ դուք պարզապես պետք է ներմուծեք այս մոդուլը Python-ի ցանկացած նախագծի մեջ, և դուք կարող եք աշխատել տվյալների հետ:

Ես կանխատեսում եմ ձեր հարցը՝ «ինչու՞ SQLite»: Հիմնական պատճառն այն է, որ տվյալների բազան միայն կարդալու է, ուստի SQLite-ում գրելու հետ կապված խնդիրները չպետք է մեզ անհանգստացնեն: Երկրորդ, այս DBMS-ի ձևաչափը հարմար է. այն ավելի հեշտ է դիտել (կան բազմաթիվ անվճար կոմունալ ծառայություններ, ներառյալ FireFox-ի սուպեր ընդլայնումը): Երրորդ, որոշ դեպքերում անհրաժեշտ էր մուտք գործել բաժանորդներ այն մեքենաներից, որոնք կապ չունեն MySQL սերվերի հետ: Այս դեպքում բավական է պատճենել SQLite տվյալների բազայի ֆայլը, և այս մեքենան հասանելի կլինի ամբողջ տեղեկատվությանը:

Բեռնաթափումը տեղի է ունենում օրը մեկ անգամ՝ գիշերը։ Տվյալների մուտքագրումը 1C-ում կարող է ավտոմատացվել նույն կերպ: Օրինակ, պահանջվում է գրանցել բաժանորդների թողած ընթերցումները անձնական հաշվի կայքում: Այս դեպքում մենք կրկին միանում ենք 1C-ին և ծրագրային կերպով ստեղծում և տեղադրում ենք «Ընթերցումների ակտ» փաստաթուղթը: Ստորև կներկայացնեմ կոդը:

Python-ում COM օբյեկտների հետ աշխատելը մի փոքր անսովոր է: Նախ, կոդի «pythonicity» կորել է. 1C-ում փոփոխականների և գործառույթների անվանման կանոնները, մեղմ ասած, չեն համապատասխանում Python-ի Zen-ին: Երկրորդ, բոլորը գիտեն, որ 1C օբյեկտները հաճախ անվանում են կիրիլիցա նիշերով, ինչը խնդիրներ կառաջացնի Python-ում զարգանալիս... բայց դրանք լուծելի են։ Առաջարկում եմ դիտել կոդը.

Ներմուծել pythoncom ներմուծում win32com.client V82_CONN_STRING = "Srvr=v8_server;Ref=v8_db;Usr=username;Pwd=megapass;" pythoncom.CoInitialize() V82 = win32com.client.Dispatch("V82.COMConnector").Connect(V82_CONN_STRING)

Ինչպես երևում է ծածկագրից, հաճախորդը սկզբնավորվում է 1C-ի հետ աշխատելու համար: COM օբյեկտը սահմանվում է «V82.COMConnector» անունով: Խնդրում ենք նկատի ունենալ, որ այս անունը վավեր է V8.2 հարթակի համար, եթե ունեք 8.1 տարբերակ, ապա անունը կլինի «V81.COMConnector»:

Մենք կոչում ենք Connect() մեթոդը սկզբնականացված հաճախորդի վրա՝ փոխանցելով այն կապի տողը: Տողը բաղկացած է սերվերի անունից, տվյալների բազայից, օգտվողից և գաղտնաբառից: Ստացված V82 օբյեկտը պահպանում է կապը 1C հավելվածին: Այն չունի Disconnect() մեթոդ կամ նման բան: Տվյալների բազայից անջատվելու համար պարզապես ջնջեք օբյեկտը հիշողությունից՝ օգտագործելով del() ֆունկցիան կամ վերագրեք այն None փոփոխականին։

Ունենալով օբյեկտ՝ կարող եք մուտք գործել 1C գլոբալ համատեքստի ցանկացած դաշտ և մեթոդ, գործել ունիվերսալ օբյեկտներով, ինչպիսիք են TabularDocument, ValueTable և այլն: Կարևոր է նշել, որ COM կապի միջոցով աշխատելիս 1C-ն աշխատում է «Արտաքին կապ» ռեժիմով: Այն թույլ չի տալիս որևէ ինտերակտիվ գործառույթ, ինչպիսիք են թռուցիկ պատուհանները, ծանուցումները և, ամենակարևորը, ձևերը: Համոզված եմ, որ դուք մեկ անգամ չէ, որ անիծելու եք կոնֆիգուրացիայի մշակողներին, ովքեր փաստաթղթի ձևի մոդուլում ներառել են Button1Press() ընթացակարգի ամենակարևոր գործառույթը:

Եկեք խոսենք այնպիսի կարևոր բանի մասին, ինչպիսին է կիրիլյան ատրիբուտները: Չնայած այն հանգամանքին, որ 1C-ը երկլեզու միջավայր է, և յուրաքանչյուր ռուսերեն մեթոդի համար կա անգլերեն լեզվով անալոգ, վաղ թե ուշ ձեզ հարկավոր է դիմել կիրիլյան հատկանիշին: Եթե ​​դա որևէ խնդիր չի առաջացնում PHP կամ VBScript լեզուներում,

Սահմանել Con = CreateObject("v81.COMConnector") Սահմանել v8 =Con.Connect("Connection string") Set AccountsManager = v8.Documents.Accounts.... Սահմանել AccountsRecord= AccountsManager.CreateItem() AccountsRecord.Account = ... .... AccountsRecord.Write()

Այնուհետև Python կոդը պարզապես կխափանվի շարահյուսական սխալի հետ: Ինչ անել? Խմբագրե՞լ կոնֆիգուրացիան: Ոչ, բավական է օգտագործել getattr և setattr մեթոդները։ Այս ֆունկցիաներին փոխանցելով COM օբյեկտ և հատկանիշի կիրիլիցա անունը՝ կարող եք ստանալ և սահմանել արժեքներ համապատասխանաբար.

#coding=cp1251 catalog = getattr(V82.Catalogs, «Personal Accounts»)

Հետևյալը կարևոր է. մանրամասների անվանումները, ինչպես նաև գործառույթների և մեթոդների պարամետրերը պետք է փոխանցվեն cp1251 կոդավորման մեջ: Հետևաբար, կոդավորումների հետ նախապես շփոթելուց խուսափելու համար իմաստ ունի այն հայտարարել ֆայլի սկզբում՝ #coding=cp1251։ Դուք կարող եք այնուհետև փոխանցել տողերը՝ առանց անհանգստանալու դրանց կոդավորման մասին: Բայց! 1C-ից ստացված բոլոր տողերը (զանգող գործառույթների արդյունքները, հարցումները) կլինեն UTF-8 կոդավորման մեջ:

Կոդի օրինակ, որը հարցում է կատարում 1C միջավայրում, կրկնում է արդյունքի միջով և պահպանում տվյալների բազան SQLite-ում.

#coding=cp1251 q = """ SELECT Personal Accounts. Code AS code, Personal Accounts. Building. Settlement. Name + ", " + Personal Accounts. Կարճ Հասցե AS հասցե, Անձնական Հաշիվներ. Բաժանորդ. Անուն AS fio, Personal Accounts. Բաժին AS, ԷՔՍՊՐԵՍ (Personal Accounts of the Last Փողոց, Անձնական Հաշիվներ AS Personal S, Զույգ.Գլխավոր սենյակ.Համար AS բնակարան, PersonalAccounts.Division.Parent.Name AS mro FROM Directory.PersonalAccounts AS PersonalAccounts LEFT CONNECTIONInformation. ALUE (տեղեկատու. Բնութագրերի տեսակները.աշխարհագրական ցանցի կազմակերպում) AS բնութագրեր Անձնական հաշիվներ Հղում = Անձնական հաշիվների բնութագրերը Վերջին օբյեկտի «» հարցումը = V82.NewObject («Հարցում», q) ընտրություն = հարցում: Execute().Choose() CONN = db.connect() CONN.query(models.Abonent).delete() while selection.Next(): abonent = models.Abonent() abonent.account = selection.code.strip( ) abonent.code = selection.code abonent.fio = selection.fio abonent.address = selection.address abonent.psu = selection.psu abonent.tso = ընտրություն tso abonent.source = u"ASRN" abonent.np = ընտրություն. np abonent.street = selection.street abonent.house = selection.house abonent.flat = selection.flat abonent.mro = selection.mro CONN.add(abonent) CONN.commit()

Այստեղ CONN-ը SQLite տվյալների բազայի հետ կապի նիստն է: Ստեղծվում է հարցման օբյեկտ և լրացվում է դրա տեքստը: Ինչպես նշվեց վերևում, հարցման տեքստը պետք է լինի cp1251, որի համար նախապես հայտարարված է կոդավորումը: Հարցումը կատարելուց հետո բոլոր բաժանորդները ջնջվում են տվյալների բազայում, որպեսզի կրկնօրինակներ չավելացվեն, այնուհետև դրանք ավելացվում են ցիկլով և հետևում է վերջնական commit-ը։

Հարցումների հետ աշխատելիս ես հայտնաբերեցի հետևյալ կանոնները.

Դաշտերը ընտրելիս նրանց անունները նշանակեք լատինատառ տառերով, շատ ավելի հարմար կլինի դրանց մուտք գործել ընտրիչով (կետ), փոխանակ getattr():
- Ընտրեք միայն պարզունակ տվյալների տեսակները՝ տողեր, թվեր, ամսաթիվ և բուլյան: Երբեք մի ընտրեք որևէ օբյեկտի (փաստաթուղթ, տեղեկատու) հղումներ: Այս համատեքստում ձեզ բացարձակապես պետք չեն հղումներ և նույնիսկ վնասակար են, քանի որ ցանկացած զանգ դեպի հղում կամ մեթոդ կհանգեցնի հարցում COM կապի միջոցով: Եթե ​​դուք մուտք գործեք կապի ատրիբուտները հանգույցով, ապա այն չափազանց դանդաղ կլինի:
- Եթե ընտրեք Date տեսակի դաշտ, այն կվերադարձվի որպես PyTime օբյեկտ: Սա հատուկ տվյալների տեսակ է COM կապով ամսաթիվ-ժամը փոխանցելու համար: Դրա հետ աշխատելն այնքան էլ հարմար չէ, որքան սովորական ամսաթվի դեպքում: Եթե ​​այս օբյեկտը փոխանցեք int(-ին), այն կվերադարձնի ժամանակի դրոշմակնիք, որից հետո կարող եք ստանալ datetime-ը՝ օգտագործելով fromtimestamp() մեթոդը:

Հիմա եկեք տեսնենք, թե ինչպես են ձևավորվում տպագիր փաստաթղթերը: Բանն այն է, որ սպառողին պետք է հնարավորություն տրվի ներբեռնելու նախապես պատրաստված փաստաթղթեր, օրինակ՝ վճարման անդորրագիր կամ հաշտության հաշվետվություն։ Այս փաստաթղթերը ստեղծվում են 1C-ում` ըստ սահմանված պահանջների, դրանց իրականացումը Python-ում շատ ժամանակ կպահանջի: Հետևաբար, ավելի լավ է փաստաթղթեր ստեղծել 1C-ով և պահպանել դրանք Excel ձևաչափով:

Այսպիսով, հաշտեցման հաշվետվության փաստաթուղթը ստեղծվում է հատուկ արտաքին մշակմամբ: Նրանց համար, ովքեր ծանոթ չեն 1C տերմինաբանությանը. մշակումը ինքնուրույն ծրագիր է, որն ունի իր սեփական մոդուլը, ձևաթղթերը, ձևանմուշները, որոնք նախատեսված են 1C միջավայրում աշխատելու համար: Անհրաժեշտ է նախաստորագրել մշակումը, լրացնել դրա մանրամասները և կանչել գործառույթ, որը մեզ կվերադարձնի աղյուսակային փաստաթուղթ, որը նախատեսված է 1C-ում դիտելու համար: Այս փաստաթուղթը պետք է պահպանվի Excel ձևաչափով և պատճենվի սերվերում կամ գրանցվի տվյալների բազայում:

Հղում = getattr(V82.Catalogs, «System Reports»).FindByDescription(«Ellen Reconciliation Report») nav_url = V82.GetURL(link, «Report») name = V82.ExternalReports.Connect(nav_url) ExternalReport = V82.Ex Ստեղծել (անուն) setattr(ExternalReport, «PersonalAccount», հղում) table_doc = ExternalReport.GetDoc() ուղի = V82.GetTempFileName(«xls») table_doc.Write(ուղիղ, V82 .SpreadsheetDocumentFileType.XLS) report .account = reference.Code.strip() report.type = u"act" report.document = open(path, "rb").read() CONN.add(report)

Վերոնշյալ հատվածը կատարում է հետևյալը. Փաստաթուղթը գեներացնող մշակումը միացված է: Մշակումը կարող է ներկառուցվել կոնֆիգուրացիայի մեջ, պահվել սկավառակի վրա կամ 1C տվյալների բազայում (որոշ գրացուցակում): Քանի որ մշակումը հաճախ փոխվում է, որպեսզի ամեն անգամ կոնֆիգուրացիան չթարմացվի, ամենահաճախ փոփոխվող մշակումը պահվում է «Համակարգի հաշվետվություններ» գրացուցակում՝ «արժեքի պահեստավորում» ատրիբուտում, որը կոչվում է Report: Մշակումը կարող է սկզբնավորվել՝ այն բեռնաթափելով տվյալների բազայից սկավառակ և բեռնելով այն, կամ օգտագործելով GetURL() մեթոդը, որին պետք է հղում փոխանցել գրացուցակի տարրին և հատկանիշի անունը։ Մենք մանրամասների արժեքները վերագրում ենք ստացված մշակման օբյեկտին, կանչում ենք արտահանվող ֆունկցիան GetDoc() և ստանում աղյուսակի փաստաթուղթ, որը պահվում է ժամանակավոր Excel ֆայլում: Այս ֆայլի բովանդակությունը գրված է SQlite տվյալների բազայում:

Վերջին բանը, որ մնում է դիտարկել, տվյալների ծրագրային մուտքագրումն է 1C: Ենթադրենք, որ անհրաժեշտ է մուտքագրել բաժանորդների ցուցմունքները։ Դա անելու համար բավական է ստեղծել և իրականացնել «Վկայություն վերցնելու ակտ» փաստաթուղթը.

#coding=cp1251 acts = getattr(V82.Documents, "Act of Act of Weditiony") act = acts.CreateDocument() setattr(act, "Testimony", 1024.23) setattr(act, "Bubscriber", "Ivanov") # Լրացում այլ մանրամասներով .. ակտ. Գրել()
Տվյալների մուտքագրումն այժմ ավտոմատացված է:

Այսպիսով, ես նախանշեցի մի մեթոդ, որը հիմնված է տվյալների ծրագրային վերբեռնման և ներբեռնման վրա՝ օգտագործելով COM կապը: Այս մեթոդը հաջողությամբ գործում է իմ կազմակերպությունում արդեն գրեթե մեկ տարի։ Տվյալների բազան, որը ձևավորվել է 1C-ից, սպասարկում է 3 վճարային համակարգեր, ինտերնետ էքվայրինգ (քարտերով վճարում ինտերնետի միջոցով), ինչպես նաև անձնական հաշիվ։ Բացի այդ, տարբեր սկրիպտներ միացված են տվյալների շտեմարանին՝ ռեժիմն ավտոմատացնելու համար:

Չնայած մեթոդի թերություններին (COM կապի դանդաղ արագություն), ընդհանուր առմամբ այն կայուն է գործում: Մենք ունենք տվյալներ հարթակից անկախ ձևով (SQLite), որոնց հետ կարելի է աշխատել ցանկացած լեզվից: Իսկ կոդի հիմնական մասը գրված է Python-ով, ինչը նշանակում է, որ հասանելի են բազմաթիվ գործիքներ և տեխնիկա, որոնց մասին նույնիսկ չես կարող երազել 1C-ում:

Սա 1C-ի հետ փոխազդելու հնարավոր ուղիներից մեկն է: Համոզված եմ, որ այն նոր չէ և հավանաբար արդեն ինչ-որ մեկի կողմից փորձարկված ու օպտիմալացված է։ Այնուամենայնիվ, ես փորձեցի հնարավորինս շատ մանրամասներ ներկայացնել գործընթացից, որպեսզի պաշտպանեմ ձեզ այն ծուղակներից, որոնց վրա ես ինքս ոտք դրեցի:

Բոլորիդ հաջողություն եմ մաղթում և հիշեք, որ 1C-ն այնքան էլ սարսափելի չէ, որքան ենթադրվում է:

Երկու տեղեկատվական բազաների միջև տեղեկատվության փոխանակման համար՝ առանց ավելորդ վերբեռնումների և փոխանակման ֆայլերի, չկա ավելի լավ բան, քան COM կապը: Եվ դրա հետ դժվար է վիճել, քանի որ այս տեսակի կապի օգտագործումը բավականին պարզ և կայուն է: Բայց այս մեխանիզմում կա մեկ շեղ և տհաճ տեղ, մենք խոսում ենք մեկ այլ բազայի հետ կապ հաստատելու համար։ Որոշ դեպքերում այն ​​կարող է հասնել բավականին մեծ արժեքների, այսինքն. լինել շատ երկար.

Ինչ է պատահել?

COM կապի միջոցով միացման պահին միացված տվյալների բազան ամբողջությամբ բեռնում է տվյալների բազայի կոնֆիգուրացիան, որին մենք միանում ենք: Փորձելով, օրինակ, միանալ Enterprise Accounting տվյալների բազային, սպասման ժամանակը բավականին երկար կտևեր, քանի որ կազմաձևման ծավալը կազմում է հարյուրավոր մեգաբայթ: Պարզ է դառնում, որ ավելի արագ շահագործման համար բոլոր կապերը պետք է պահվեն և պահպանվեն:

Կատարման վերլուծություն

Եկեք հարցնենք ինքներս մեզ, թե արդյոք անհրաժեշտ է ընդհանրապես կապեր քեշավորել և արդյոք դա արդյունք կտա, երբ օգտվողը ինտենսիվ աշխատում է COM կապով: Եկեք չափենք միացման ժամանակը մինչև 20 կԲ կոնֆիգուրացիա:

Մենք տեսնում ենք, որ փոքր բազայի միացումը տևել է 3,5 վայրկյան: Ավելի մեծ տվյալների բազայի միանալու ժամանակ ժամանակը մի քանի անգամ կավելանա:

Պահպանված կապը պահելիս այս գործողությունները մի քանի կարգի մեծության ավելի քիչ ժամանակ կպահանջեն:

Ինչպե՞ս կարող ենք ակտիվ պահել մեր COM կապը:

Խնդիրն այն է, որ 1C հարթակը չի տրամադրում ստանդարտ գործիքներ տեղեկատվական անվտանգության մեջ COM կապերը պահելու համար։ Անիմաստ է կապը պահել գրացուցակներում և փաստաթղթերում, քանի որ այն հաճախ կարող է փոխվել: Ամենահեռանկարային տարբերակն այն է, որ կապը պահվի նիստի պարամետրում: Բայց նույնիսկ այստեղ ամեն ինչ այնքան էլ հարթ չէ։ Ի վերջո, չկա մեկ հարմար տվյալների տեսակ COM կապը պահելու համար:

Այս փաստարկները հանգեցնում են նրան, որ պահեստավորումը հնարավոր է միայն հաճախորդի վրա որոշ փոփոխականում: Դիտարկենք կառավարվող ձևի տարբերակը: Անհրաժեշտ է փոփոխականը ձևակերպել &OnClient հրահանգով, որտեղ մենք կպահենք կապի արժեքները։ Համապատասխանաբար, դուք կարող եք նաև զանգահարել այս կապը միայն հաճախորդի վրա, քանի որ չեք կարող COM օբյեկտ փոխանցել հաճախորդից սերվեր: Սովորական ձևերի համար սերվերի և հաճախորդի միջև տարանջատում չկա, և այս մեխանիզմը դառնում է ավելի պարզ: Մի մոռացեք փակել կապը նախքան ձեր օգտագործած ձևը փակելը` հիշողության արտահոսքը կանխելու համար:

Արդյունքի փոխարեն

Չնայած այս սխեման լուծում է որոշ կատարողական խնդիրներ, այն հեռու է իդեալական լինելուց: Յուրաքանչյուր ձև, որտեղ անհրաժեշտ կլինի աջակցել COM կապին, նոր նիստ կստեղծի ստացողի տեղեկատվական բազայում, և համապատասխանաբար ավելի մեծ թվով լիցենզիաներ կպահանջվեն: Նաև հիմնական թերություններից մեկը սերվերին միանալու աջակցության բացառումն է

Հաջորդ հոդվածում կքննարկվի ավելի առաջադեմ մեթոդ, որը վերացնում է այս խնդիրները (միացում վեբ ծառայությունների միջոցով):



Առնչվող հրապարակումներ