Configurarea unei conexiuni com 1c 8.3. Trei balene de lucru cu obiecte COM. Lucrul printr-o conexiune COM este mai ușor decât ați crede. Obținerea și compararea unei enumerari printr-o conexiune COM

Una dintre modalitățile de a transfera date dintr-o configurație 1C în alta este conexiune software folosind COM. Multe companii folosesc mai multe baze diferite, între care trebuie să existe anumite conexiuni și dependențe. Dacă este necesar nu numai să transferați date, ci și să efectuați anumite procesări de date, atunci o conexiune COM va fi mecanismul optim. Capacitatea de a analiza date dintr-o altă bază de date 1C este utilă oricărui dezvoltator.

Ne conectăm prin COM la baza de date 1C

Pentru a implementa o conexiune COM în 1C, se folosește un mecanism special numit COMConnector. Acest obiect este instalat împreună cu platforma și este utilizat pentru comunicare baze de informare. Trebuie remarcat faptul că pentru versiunile 8.2 și 8.3 sunt folosite obiecte cu nume diferite - „V82.COMConnector” și respectiv „V83.COMConnector”.

Amintiți-vă că o licență este cheltuită pe durata conexiunii COM la baza de date - nu ar trebui să vă lăsați duși de a face mai multe conexiuni în același timp. Acest lucru este important în special pentru organizațiile care au un număr limitat de licențe. Această problemă poate fi rezolvată cu ajutorul sarcinilor de rutină care sunt efectuate în timpul absenței conexiuni active utilizatorii la baza de informații.

Pentru a vă putea conecta la o altă bază de date și a solicita informatie necesara trebuie sa cunosti urmatoarele date:

  1. Ce tip este - fișier sau client-server;
  2. Unde este localizat;
  3. Sub ce nume și ce parolă le puteți introduce;
  4. Ce date vă interesează.

Din primele trei puncte, pentru a implementa o conexiune COM, trebuie să formați un șir de parametri. În funcție de tipul de IB, acesta va diferi aspect. Folosind șirul primit, se realizează o conexiune cu care puteți colecta date dintr-o altă bază de date pentru analiză și prelucrare prin orice metodă.

ConnectionParametersFileIB = "File=""Path_to_base""; Usr=""User_name"";Pwd=""Parolă"""; ConnectionParametersClientServerIB = "Srvr=""Server_Name""; Ref=""Base_Name""; Usr=""User_Name""; Pwd=""Parolă""";

Funcția de conectare este simplă și nu ar trebui să ridice întrebări dacă toți parametrii sunt corecti. Pentru a accelera depanarea și analiza posibile erori este mai bine să includeți conexiunea într-un construct Attempt. Funcția va returna o valoare de tipul „Obiect COM”, cu care va trebui să lucrați, obținând datele necesare.

&AtServer Funcția ConnectToBase() export ConnectionParametersIB = "Fișier=""E:\base 1c\ERP""; Usr=""Administrator"";Pwd=""1"""; V83COMCon= New COMObject ("V83.COMConnector"); Încercați returnarea V83COMCon.Connect(ConnectionParametersIB); Raport de excepție(ErorDescription()); Returnare nedefinită; Sfârșitul încercării; EndFunctions

Printr-o conexiune COM, puteți nu numai să selectați date, ci și să le adăugați la baza de date la care vă conectați. Amintiți-vă că putem transfera 4 tipuri de date primitive printr-un obiect COM. Alte tipuri vor trebui specificate folosind funcțiile de căutare încorporate în platformă. Te rog noteaza asta funcții globale platformele sunt de asemenea apelate printr-o conexiune COM.

Primim date din baza de date 1C

După ce ați primit obiectul dorit, trebuie să citiți datele dintr-o altă bază de date. Pentru a face acest lucru, aplicăm o solicitare printr-o conexiune COM în 1C 8.3 folosind valoarea primită de tipul „Obiect COM” din funcție. Este important să vă conectați mai întâi la baza de date și apoi să executați interogarea. Execuția are loc prin metoda NewObject cu indicarea tipului obiectului sub formă de șir - „Solicitare” ca parametru.

&OnServer Procedura TestCOMOnServer() Conexiune = ConnectToBase(); Dacă TypeValue(Connection) Type("Nedefinit"), atunci QueryBPO = Connection.NewObject("Query"); Interogare BPZO.Text = "SELECTAȚI primele 15 | Director utilizator. Nume AS Nume | FROM | Director utilizator AS Director utilizator"; Selecție = QueryBPO.Run().select(); While Sample.next() loop Report(Selection.Number); EndCycle; EndIf; Sfârșitul procedurii >

De exemplu, pentru a obține informații despre utilizatorii unui anumit departament, vom stabili o condiție în cerere prin parametri. Un parametru va fi de tip simplu - un șir, iar departamentul - o legătură către elementul directorului „Structura întreprinderii”. Rezultatul interogării este un tabel cu câmpuri enumerate de tipul în care există în baza de date la care a avut loc conexiunea COM. Dacă trebuie să le convertiți în alte tipuri, utilizați specificații standard platforme:

  • Linia();
  • Număr();
  • Data de().
RequestBPO = Connection.NewObject("Solicitare"); QueryBPO.Text = "SELECT first 15 | User Directory.Name AS Nume |FROM | Directory.Users AS User Directory I WHERE | User Directory.Department = &DesiredDepartment | Și UserDirectory.Name ca ""%"" + &DesiredName+ ""%" "" ; BPZO Request.SetParameter("Departamentul dorit", Connection.Directories.Enterprise Structure.FindByCode("00-000023")); RequestBPO.SetParameter("RequiredName","Ekaterina"); Selecție = QueryBPO.Run().select(); While Selection.next() loop Report(Selection.Name); EndCycle;

Dacă trebuie să transferați o matrice în baza de date pentru selectare după mai mulți parametri, de exemplu, diviziuni, se folosește și comanda NewObject. În mod similar, puteți trece o listă sau un tabel de valori, completându-le cu elemente ale unei alte baze de date prin conexiune. Toate sunt disponibile pentru căutare. metode existente obiectele și mecanismele platformei.

RequestBPO = Connection.NewObject.(„Solicitare”); QueryBPO.Text = "SELECT first 15 | User Directory.Name AS Nume | FROM | Directory.Users AS User Directory I WHERE | User Directory.Department In (&DesiredDepartment) | Și UserDirectory.Name ca ""%"" + &DesiredName+ "" %" ""; Subdivisions Array = Connection.NewObject("Matrice"); Departamente array.Add(Connection.Catalogs.EnterpriseStructure.FindByCode("00-000023")); Departamente array.Add(Connection.Catalogs.EnterpriseStructure.FindByCode("00-000038")); Departamente array.Add(Connection.Catalogs.EnterpriseStructure.FindByCode("00-000046")); BPZO Request.SetParameter("Subdiviziune dorită", Matrice de subdiviziuni); RequestBPO.SetParameter("RequiredName","Ekaterina"); Selecție = QueryBPO.Run().select(); While Selection.next() loop Report(Selection.Name); EndCycle;

La transferul documentelor sau elementelor directoarelor, se pune întotdeauna problema controlului transferului unui anumit obiect. Cu conexiunile COM, puteți rezolva astfel de probleme printr-un identificator unic. Trebuie să găsiți un obiect în baza de date conectabilă după identificatorul din IB-ul curent folosind funcția „GetLink”, folosind identificatorul ca șir. Dacă nu există, îl puteți crea folosind o conexiune COM.

StrIdent = String(Directories.Users.FindByCode("00-0000313"). UniqueIdentifier()); Dacă NU este ValueFilled(Connection.Catalogs.Users.GetReference(Connection.NewObject("UniqueIdentifier", StrIdent))) atunci NewUser = Connection.Catalogs.Users.CreateItem(); NewUser.Name = Directories.Users.FindByCode("00-0000313").Name; NewUser.Individual = Directories.Users.FindByCode("00-0000313").Individual; NewUser.Write(); EndIf;

De asemenea, conexiunea COM are dreptul de a utiliza proceduri și funcții din modulele comune 1C cu proprietatea „Conexiune externă” activată. Pe lângă această condiție, funcția sau procedura apelată trebuie să fie o funcție de export și să nu includă acțiuni interactive efectuate pe server. În caz contrar, veți vedea o eroare despre operația nevalidă.

Compus..; VariableFromFunction = Conexiune...; apel de funcție>nume modul comun>apel de procedură>nume modul comun>

Posibilitățile de conectare externă cu o altă bază de date în 1C sunt destul de extinse și vă pot permite să efectuați multe sarcini. Este important să puteți evalua corect setul de instrumente și să alegeți soluție optimă. În cele mai multe cazuri, această abilitate apare numai cu experiență sau prin studierea exemplelor de muncă ale profesioniștilor cu experiență.

Imprimare (Ctrl+P)

Una dintre opțiunile pentru schimbul de date între bazele de date 1C este un schimb prin intermediul unei conexiuni COM. Folosind o conexiune COM, vă puteți conecta de la o bază de date 1C la alta și puteți citi sau scrie date. Puteți utiliza această metodă atât în ​​versiunile client-server ale bazelor de date, cât și în bazele de date de fișiere. Acest articol discută acest tip de conexiuni pe platforma 8.3

conexiune com

Puteți crea două tipuri de obiecte COM pentru aplicația 1C. Sunt conexiuni vechi V83.Aplicație și conexiuni com V83.COMConector . In caz de V83.Aplicație este lansată o copie aproape completă a aplicației 1C. În caz de utilizare V83.COMConector o mică partea de server. Viteza de lucru în acest caz este mai mare, dar este posibil ca unele funcții să nu fie disponibile. În special, lucrul cu formulare și cu module comune pentru care nu este setată proprietatea de a lucra cu conexiuni externe. Ar trebui să utilizați în principal V83.COMConectorși numai în caz de lipsă de funcționalitate V83.Aplicație. Diferența de viteză poate fi vizibilă în special pe bazele de date mari. Pentru platforma se folosește 8.2 V82.Application sau V82.COMConnector

Stabiliți o conexiune OLE

Conexiune = New COMObject(“V83.Application” );

Stabiliți conexiunea COM

Conexiune = New COMObject(“V83.COMConnector” );

Șir de conexiune

//Pentru opțiunea client-server
StringConnection= „Srvr = „ „ServerName” „;Ref = „ „BaseName” ;
//Pentru opțiunea mod fișier:
StringConnection= „Fișier = „ „PathBase” „; Usr = Nume de utilizator; Pwd = Parolă”;
Atentat, încercare
Connection = Conexiune . Conectați(ConnectionString) ;
Excepție
Mesaj = New MessageToUser;
Mesaj . Text = „Nu s-a putut conecta la baza de date” + DescriereEroare(); Mesaj . A raporta();
EndTry ;

Ruperea conexiunii

Conexiune = nedefinit ;
Pentru obiect V83.Aplicație este obligatoriu să deconectați conexiunea, în caz contrar o sesiune incompletă va rămâne suspendată, care va trebui apoi ștearsă manual. In caz de V83.COMConector conexiunea se termină automat la sfârşitul procedurii în care s-a făcut legătura.Şi mai este un mic moment. Pentru utilizatorul sub care se realizează conexiunea, caseta de selectare „Cereți confirmarea la închiderea programului” din setările acestuia trebuie să fie dezactivată.

Metoda NewObject().

Pentru a crea un obiect nou, puteți utiliza metoda NewObject(), de exemplu:

Pentru V83.COMConector

SolicitațiCOM = Conexiune. NewObject( "Cerere ") ;
TableCOM = Conexiune. NewObject( „Tabelul cu valori”) ;
ArrayCOM = Conexiune. NewObject("Matrice");

WidCOM = Connection.NewObject

Pentru V83.Aplicație

QueryOLE = Conexiune. NewObject(“ Cerere ") ;
TableOLE = Conexiune. NewObject(„Tabelul cu valori”) ;
ArrayOLE = Connection.NewObject(„Matrice”);
WidCOM = Connection.NewObject(„UniqueIdentifier”,StringUID);

SolicitațiCOM . Text ="ALEGE
| Pozițiile organizațiilor. Cod,
| Funcțiile organizațiilor.Nume
| DE LA | Director.PozițiiOrganizații
AS pozițiile organizațiilor”;

Rezultat = SolicitareCOM. A executa () ;
Probă = rezultat. Alegeți () ;
În timp ce selecția. Următorul()Ciclu
EndCycle ;
De asemenea, puteți utiliza manageri de obiecte de configurare:
DirectoryCOM = Conexiune. Carti de referinta. DirectoryName;
DocumentCOM = Conexiune. Documentație. Numele documentului;
RegisterCOM = Conexiune. Informații despre registre. RegisterName;

Obținerea și compararea unei enumerari printr-o conexiune COM

Pentru a compara valorile elementelor de enumerare definite în configurație, este necesar să convertiți aceste elemente într-unul dintre tipurile primitive, a căror comparație nu provoacă dificultăți. Aceste tipuri pot fi fie numerice, fie de tip șir. Puteți converti valoarea unui element de enumerare într-un tip numeric ca acesta

Enum element = Connection.Directories.Directory1.FindByCode(1).Attribute1;

PossibleValues ​​​​= EnumElement.Metadata().EnumValues;

EnumElementNumber = PossibleValues.Index(PossibleValues.Find(Connection.XMLString(EnumElement)));

Dacă EnumItemNumber = 0, atunci Raportați( „EnumValue1”);

ElseIf EnumItemNumber = 1 Apoi Raport("ValoareEnum2");

EndIf;

Obținerea unui obiect prin COM prin ID

Prin managerii de obiecte de configurare obținem un obiect com, de exemplu:
DocumentCOM = Conexiune. Documentație. Numele documentului;

Apoi obținem șirul de identificare unic:

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

ID = Y nou unicID(StringUID);
CU linkByIdentifier = Documente[DocumentName].GetLink(Identifier);

Dacă trebuie să găsiți obiectul com după document prin ID, atunci trebuie să scrieți astfel:

WidCOM = Connection.NewObject(„UniqueIdentifier”,StringUID);
LinkByIdentifier = Connection.Documents[DocumentName].GetLink(UidCOM);

Una dintre opțiunile pentru schimbul de date între bazele de date 1C este un schimb prin intermediul unei conexiuni COM.

Folosind o conexiune COM, vă puteți conecta de la o bază de date 1C la alta și puteți citi sau scrie date. Puteți utiliza această metodă atât în ​​versiunile client-server ale bazelor de date, cât și în bazele de date de fișiere. În acest articol, vom analiza exemple de astfel de compuși. Exemplele folosesc platforma 8.2.

Puteți crea două tipuri de obiecte COM pentru aplicația 1C. Acest V82.AplicațieȘi V82.COMConector. In caz de V82.Aplicație este lansată o copie aproape completă a aplicației 1C. în caz de utilizare V82.COMConector este pornită o mică parte de server.
Viteza de lucru în acest caz este mai mare, dar este posibil ca unele funcții să nu fie disponibile. În special, lucrul cu formulare și cu module comune pentru care nu este setată proprietatea de a lucra cu conexiuni externe. Ar trebui să utilizați în principal V82.COMConectorși numai în caz de lipsă de funcționalitate V82.Aplicație. Diferența de viteză poate fi vizibilă în special pe bazele de date mari.

Asadar, haideti sa începem

  1. Să creăm un obiect COM
    • Pentru V82.Aplicație Conexiune = New COMObject("V82.Application" );
    • Pentru V82.COMConector Conexiune = New COMObject("V82.COMConnector");
  2. Să creăm un șir de conexiune
    • pentru versiunea de server a bazei de date ConnectionString = "Srvr = " "ServerName" ";Ref = " "BaseName" ;
    • pentru versiunea de fișier a bazei de date ConnectionString = "File = " "PathKBase" "; Usr = Nume utilizator; Pwd = Parolă";
  3. Realizarea unei conexiuni la baza de date Attempt Connection = Conexiune. Connect(ConnectionString) ; Mesaj de excepție = New MessageToUser; Mesaj. Text = + DescriptionErrors() ; Mesaj. A raporta() ; EndTry ;
  4. Deconectarea de la bază Conexiune = nedefinit ;

    Pentru obiect V82.Aplicație este obligatoriu să deconectați conexiunea, în caz contrar o sesiune incompletă va rămâne suspendată, care va trebui apoi ștearsă manual. In caz de V82.COMConector conexiunea se termină automat la sfârşitul procedurii în care s-a făcut legătura.Şi mai este un mic moment.

    Pentru utilizatorul sub care se realizează conexiunea, caseta de selectare „Cereți confirmarea la închiderea programului” din setările acestuia trebuie să fie dezactivată.

Și acum să punem tot codul împreună

Conexiune = New COMObject("V82.Application" ); //Conexiune = New COMObject("V82.COMConnector"); ConnectionString = "Srvr = ""Server1C"";Ref = ""MyBase""; Usr = Peter; Pwd = 123" ; //ConnectionString = "Fișier = ""С:\MyBase""; Usr = Peter; Pwd = 123"; Attempt Connection = Conexiune. Connect(ConnectionString) ; Mesaj de excepție = New MessageToUser; Mesaj. Text = „Nu se poate conecta la baza de date”+ DescriptionError() ; Mesaj. A raporta() ; EndTry ; Conexiune = nedefinit ;

Pentru tipul de conexiune V82.Aplicație metoda este aplicată obiectului COM care a fost creat inițial și pentru V82.COMConector metoda se aplică conexiunii. se lucrează în continuare cu cererea mijloace standard 1C. in cod arata asa:

Solicitare = Conexiune. NewObject("Solicitare"); // Pentru V82.COMConector Solicitare = Conexiune. NewObject("Solicitare"); // Pentru V82.Aplicație Cerere. Text = „SELECT | Pozițiile organizațiilor. Cod, | Funcțiile organizațiilor.Nume| DE LA | Director. Pozițiile organizațiilor AS Pozițiile organizațiilor "; Rezultat = Solicitare. A executa () ; Eșantion = Rezultat. Alegeți() ; În timp ce selecția. Next() Cycle EndCycle ;

Pentru versiunea 1C:Enterprise 8.3, totul rămâne neschimbat, cu excepția faptului că atunci când creați COMObjects, trebuie să utilizați „V83.COMConnector” sau V83.Aplicație.

) Asta e corect

În același timp, am văzut de mai multe ori când pur și simplu „decolează” publicații care nu trag nici măcar 10 puncte.
De ce s-a întâmplat asta? Probabil pentru că, evident, i-au plăcut cuiva.


Vorbesc despre asta și spun că ar fi bine să nu citești articolul prin rating pentru a înțelege cât de mult ai nevoie de el sau pentru a-l evalua nu atât de primitiv +/-. Cât despre ce mi-a plăcut, l-aș corecta așa: ea a punctat atât de mult datorită faptului că vedetele s-au format în așa fel și s-au adunat multă lume pe site și multora le-a plăcut, chiar tu înțelegi că este o chestiune. de hazard. de îndată ce articolul pleacă pagina principala atunci se găsește deja doar la cerere și așa toți trec prin voturi. Și pentru a susține pe pagina principală, din câte am înțeles, permit doar comentarii constante = promovarea articolului.
Tocmai pentru aceasta au pus magazine pe străzile străzilor - la urma urmei, de multe ori nu calitatea și relevanța produsului contează, ci patenta locului, oamenii care merg adesea cumpără ceea ce vor arunca a doua zi, doar de dragul procesului. Aceasta este o boală binecunoscută - shopomania. Sau pur și simplu creșterea fluxului crește probabilitatea cumpărătorului potrivit.

Iar argumentele pro și contra... sunt doar un fel de „mulțumesc” pentru timpul și munca petrecută


Acestea. Un minus contează și ca „mulțumesc”? Așa că am vrut să știu atitudinea dvs. față de dacă este necesar să o puneți în astfel de cazuri și cât de interesant cred alții? Fie că să-l pun atunci când articolul este dăunător / rău sau când este pur și simplu inutil / gol pentru tine.
În opinia mea, articolul arată ca doar o creștere a ratingului, deoarece:
1. Problema tipurilor date de mine a fost în general ignorată de autor, deși nu i-a fost prea lene să scrie o grămadă de comentarii.
2. Există o inexactitate clară în articol: se spune că aceasta este singura cale

V82 = New COMobject("V82.ComConnector"); Cod = ContractorCOM.Code;


dar o fac cu calm cu ajutorul procesării astfel:

Notify(Base.Directories.Counterparties.FindBy Name("LLC").Code);


si totul este bine! Și aleg conexiunea V82.ComConnector
Este cumva ciudat că autorului nu îi pasă deloc că articolul său conține astfel de probleme care au fost semnalate, dar nu reacționează în niciun fel.
3. Dar există încă o problemă când apare eroarea „Clasa nu există”.
4. Dar există o problemă când este instalat 8.2 și apoi este instalat 8.1 - încercați să faceți schimb prin OLE / COM schimb de modele UT-BP!
5. Ați putea indica principala procesare de pe site care vă permite să vă conectați universal prin OLE/COM pentru ca începătorii să nu piardă timpul, scrieți pentru ei! Apropo, dintr-un motiv oarecare, poza ei se etalează cu tine, de ce?. Și ca rezultat, 2 cuvinte pe fond și încă 6 în culise.

În general, nu arunc cu noroi în tine, ci punct lacune specifice, dar nu există nicio reacție. Dacă aceasta este experiența pe care o împărtășiți, atunci este cumva eronată și incompletă.
Adică, dacă autorul avea dorința de a colecta toate erorile, atunci ar putea măcar să asculte experiența altcuiva și să nu răspundă la comentarii. Imediat apare o situație în care cel care a citit-o știe mai multe decât autorul, îi spun (uneori greșit), și tot el ripostează. Ca urmare, toate informațiile nu sunt în articol, ci în comentarii! Amuzant! Se întâmplă adesea, dar, în același timp, nu trebuie să te odihnești pe ceea ce ți-ai dorit cel mai bine - eu arăt cum este mai bine, iar alții o arată! Includeți acest lucru în articol și va merita, nu toată lumea este interesată să citească această încăierare.

Bună Khabravchans!

În acest articol, vreau să vorbesc despre modul în care se stabilește integrarea cu platforma 1C în organizația mea. Ceea ce m-a determinat să fac asta a fost absența aproape completă a informații tehnice despre această temă. Citind diverse articole și rapoarte pe tema conectării 1C cu orice sistem informațional, ești convins din nou și din nou că toate sunt de marketing, de natură demonstrativă și niciodată tehnice, reflectând problema și esența soluției sale.

Vă avertizez că metoda în niciun caz nu pretinde a fi universală. Deoarece există multe configurații 1C în sine și sisteme de informare, limbi și platforme - chiar mai mult, numărul de combinații posibile este uriaș. Scopul meu este să demonstrez o soluție posibilă.


Ca limbaj care se va integra cu 1C, am ales Python. Este foarte potrivit pentru automatizarea proceselor. Acest lucru este facilitat de sintaxa minimalistă (codul este tastat foarte repede), biblioteca standard bogată (necesitate mai mică de module terțe), multiplatformă - cu o probabilitate mare, codul scris în sistemul de operare Linix va funcționa cu succes în Windows.

Pentru început, voi schița datele cu care vom lucra. Organizația - o companie de alimentare cu energie din regiunea Orientului Îndepărtat - deservește aproximativ 400 de mii de abonați, baza este 1C pe o configurație scrisă de sine. Pentru fiecare abonat sunt stocate plățile, angajamentele, serviciile consumate și schemele de calcul, dispozitivele de contorizare, citirile și multe alte date.

Odată ajuns în organizație a existat un program scris în Delphi și care folosea MSSQL/Firebird ca bază de date. În acele vremuri glorioase, era posibil să vă conectați la baza de date folosind orice limbă și să efectuați multe acțiuni - selectați abonați debitori, postați plățile primite, înregistrați citirile instrumentelor. Nu este surprinzător că colecția de scripturi care automatizează rutina a crescut constant. Programatorii puteau efectua orice acțiune fără a deschide programul în sine.

Din păcate, odată cu trecerea la 1C, freebie-ul s-a încheiat - nu mai era posibil să se conecteze direct la baza de date. În general, platforma 1C în sine este indivizibilă și este slab integrată cu alte sisteme. Este, după cum se spune, un lucru în sine. Când încărcați date în 1C, trebuie amintit că nu va fi atât de ușor să le extrageți de acolo. Dar având în vedere faptul că organizației i s-a cerut să implementeze sisteme de plată și Zona Personală, trebuia găsită o soluție.

Principalele sarcini cu care m-am confruntat au fost capacitatea de a obține rapid date despre un anumit cont personal - nume complet, adresă, dispozitive de contorizare, citiri de contoare, plăți, taxe. În plus, formarea documentelor - un act de reconciliere, chitanță de plată. Deci, nu există posibilitatea unei conexiuni directe la baza de date - toți cei care s-au uitat prin baza de date 1C de pe serverul SQL au văzut că a fost dificil să-și dea seama în masa de tabele precum aaa1, aaa2. Și să construiești interogări cu astfel de nume de tabele și câmpuri este pur și simplu nerealist. În plus, multe mese 1C (în special cele mai importante, cum ar fi tăierea ultimului, solduri și revoluții) sunt virtuale și sunt împrăștiate pe diferite mese fizice, adunându-se în mai multe îmbinări. Această metodă nu este potrivită.

Platforma 1C oferă posibilitatea de a vă conecta la aceasta printr-o conexiune COM. La fel ca multe programe Windows, în timpul instalării lui 1C, în sistem sunt înregistrate două obiecte COM - Automation Server și COM Connector. Puteți lucra cu ambele obiecte folosind un limbaj care acceptă tehnologia COM.

Obiectul Automation Server este o aplicație 1C care nu este aproape deloc diferită de o aplicație client obișnuită. Diferența este că în plus există o oportunitate controlul programului instanță de aplicație. Când lucrați cu obiectul COM Connector, este lansată o versiune ușoară a aplicației 1C, în care formularele nu sunt disponibile, precum și funcțiile și metodele legate de interfață și efecte vizuale. Aplicația în sine pornește în modul „Conexiune externă”. Inițializarea variabilelor globale (de exemplu, determinarea utilizatorului curent și a setărilor acestuia) trebuie efectuată în modulul de conexiune externă 1C. Dacă în modul de conexiune exterioară este apelată o funcție în cod care nu este disponibilă în acest mod, se va arunca o excepție (care va fi transmisă scriptului nostru python). Apelurile către funcții nesigure ar trebui să fie încadrate cu construcții ale formei

#Dacă NU OuterConnection, atunci avertisment ("Bună!"); #EndIf

Deoarece lucrul cu obiecte COM este o tehnologie numai pentru Windows, nu este surprinzător că nu este inclusă în distribuția standard Python. Va trebui să instalați o extensie - un set de module care oferă toate funcționalitățile necesare pentru programare sub Windows în Python. Poate fi descărcat ca un program de instalare exe deja asamblat. Extensia în sine oferă acces la registry, servicii, ODBC, obiecte COM și așa mai departe. Alternativ, puteți instala imediat distribuția ActiveState Python, în care extensia Win32 iese din cutie.

De ceva timp am experimentat cu conexiunea COM în dezvoltarea de aplicații web, în ​​special, un cont personal. Au fost identificate următoarele dezavantaje:

Conexiunea COM este lentă. Performanța scăzută este un minus binecunoscut al tehnologiei COM.
- Procesul de stabilire a unei conexiuni cu 1C, în funcție de configurație, poate dura de la 1 la 8 secunde (în cazul meu - 6 secunde). Inutil să spun că stabilirea unei conexiuni pentru fiecare solicitare va face ca fiecare pagină să se încarce în 8 secunde.
- Deoarece aplicațiile web python funcționează ca servere independente, punctul anterior poate fi compensat prin stocarea conexiunii într-o variabilă globală și restabilirea acesteia în cazul unei erori. Cum să mențin o conexiune în PHP, eu, sincer, încă nu m-am gândit.
- S-a pierdut aplicația web multiplatformă.

Pe baza punctelor enumerate mai sus, s-a decis schimbarea principiului interacțiunii, împărțindu-l în 2 părți - prima dependentă de platformă (Windows), descărcarea datelor 1C în orice format convenabil, iar a doua, independentă de platformă, capabilă să lucrul cu date fără a bănui nimic despre 1C în principiu.

Strategia de acțiune este următoarea: scriptul python se conectează la 1C, se execută interogările potriviteși încarcă datele în baza de date SQLite. Vă puteți conecta la această bază de date din Python, PHP, Java. Majoritatea proiectelor noastre sunt în python și, din moment ce urăsc să scriu manual interogări SQL brute, toate lucrările cu baza de date SQLite se fac prin ORM SQLAlchemy. A fost necesar doar să descriem structura de date a bazei de date într-un stil declarativ:

Din sqlalchemy.ext.declarative import declarative_base din sqlalchemy import Column, Integer, Numeric, DateTime, Unicode, Boolean, LargeBinary, ForeignKey Base = declarative_base() class Abonent(Base): __tablename__ = "abonents" id = Column Adevărat) cont = Column(Unicode(32), index=True) cod = Column(Unicode(32)) adresa = Column(Unicode(512)) fio = Column(Unicode(256)) sursă = Column(Unicode(16) ) psu = Column(Unicode(256)) tso = Column(Unicode(256)) np = Column(Unicode(256)) street = Column(Unicode(256)) house = Column(Integer) flat = Column(Integer) mro = Clasa Coloană(Unicode(256)) Plată(Bază): __tablename__ = „plăți” # și așa mai departe...

Acum este suficient să importați acest modul în orice proiect python și puteți lucra cu datele.

Vă prevăd întrebarea - „de ce SQLite”? Motivul principal este că baza de date este necesară doar pentru citire, așa că nu ar trebui să ne îngrijorăm cu privire la problemele legate de scrierea în SQLite. În al doilea rând, formatul acestui DBMS este convenabil - este mai convenabil să îl vizualizați (există multe utilitati gratuite, inclusiv o super extensie pentru FireFox). În al treilea rând, în unele cazuri a fost necesar să se obțină acces la abonați de la acele mașini pe care nu există nicio conexiune la serverul MySQL. În acest caz, este suficient să copiați fișierul bazei de date SQLite, iar pe această mașină veți avea acces la toate informațiile.

Descărcarea are loc o dată pe zi, noaptea. Introducerea datelor în 1C poate fi automatizată în același mod. De exemplu, este necesară înregistrarea citirilor lăsate de abonați pe site-ul contului personal. În acest caz, ne conectăm din nou cu 1C și metoda programului creăm și derulăm documentul „Act de obținere a probelor”. Voi furniza codul de mai jos.

Lucrul cu obiecte COM în Python este puțin neobișnuit. În primul rând, „pitonicitatea” codului este pierdută - regulile de denumire a variabilelor și funcțiilor în 1C, pentru a le spune ușor, nu corespund cu Zen-ul lui Python. În al doilea rând, toată lumea știe că obiectele 1C sunt adesea numite caractere chirilice, ceea ce va cauza probleme la dezvoltarea în Python... dar sunt rezolvabile. Vă sugerez să aruncați o privire la cod:

Import pythoncom import 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)

După cum puteți vedea din cod, clientul este inițializat pentru a lucra cu 1C. Obiectul COM este definit de numele „V82.COMConnector”. Vă rugăm să rețineți că acest nume este valabil pentru platforma V8.2, dacă aveți versiunea 8.1, atunci numele va fi „V81.COMConnector”.

Pe clientul inițializat, apelăm metoda Connect(), trecându-i șirul de conexiune. Șirul constă din numele serverului, baza de date, utilizator și parolă. Obiectul V82 rezultat stochează conexiunea la aplicația 1C. Nu are o metodă Disconnect() sau ceva de genul acesta. Pentru a vă deconecta de la bază, este suficient să eliminați obiectul din memorie cu funcția del () sau să atribuiți variabila la None.

Având un obiect, puteți accesa orice câmpuri și metode din contextul global 1C, puteți opera cu obiecte universale precum TabularDocument, TableValues ​​etc. Este important să rețineți că atunci când lucrați printr-o conexiune COM, 1C funcționează în modul „Conexiune externă”. Nu include nicio caracteristică pentru lucrul interactiv, cum ar fi dialoguri pop-up, notificări și, cel mai important, formulare. Sunt sigur că vei blestema dezvoltatorii de configurații de mai multe ori pentru că au inclus cea mai importantă funcționalitate în procedura Button1Press() din modulul de formular de document.

Să vorbim despre un lucru atât de important precum atributele chirilice. În ciuda faptului că 1C este un mediu bilingv și există un echivalent în engleză pentru fiecare metodă rusă, mai devreme sau mai târziu va trebui să apelezi la atributul chirilic. Dacă este pornit limbi PHP sau VBSCript nu va cauza probleme,

Set Con = CreateObject("v81.COMConnector") Set v8 =Con.Connect("Connection string") Set AccountsManager = v8.Documents.Accounts.... Set AccountsRecord= AccountsManager.CreateItem() AccountsRecord.Account =... ..... AccountsWrite.Write()

Apoi codul python se va bloca pur și simplu cu o eroare de sintaxă. Ce să fac? Editați configurația? Nu, folosește doar metodele getattr și setattr. Transmițând un obiect COM și un nume de atribut chirilic acestor funcții, puteți obține și seta valori în mod corespunzător:

#coding=cp1251 catalog = getattr(V82.Catalogs, "PersonalAccounts")

Următoarele sunt importante: numele atributelor, precum și parametrii funcției și metodei, trebuie să fie transmise în codificarea cp1251. Prin urmare, pentru a evita confuzia de codare în prealabil, este logic să o declarați la începutul fișierului: #coding=cp1251. După aceea, puteți trece șiruri fără să vă faceți griji cu privire la codificarea lor. Dar! Toate șirurile primite de la 1C (rezultate ale apelurilor de funcții, solicitări) vor fi codificate în UTF-8.

Un exemplu de cod care execută o interogare în mediul 1C, iterează peste rezultat și salvează baza de date în SQLite:

#coding=cp1251 q = """ SELECT PersonalAccounts.Code Cod AS, PersonalAccounts.Building.Location.Name + ", " + PersonalAccounts.ShortAddress AS adresa, PersonalAccounts.Subscriber.Name AS fio, PersonalAccounts.Division.Name AS psu, EXPRESS(CaracteristiciPersonalAccountsSliceLast.Value AS Directory.Territorial NetworkOrganizations).Nume AS tso, PersonalAccounts.Building.Settlement.Name AS np, PersonalAccounts.Building.Street.Name AS strada, PersonalAccounts.Building.House AS casa, Persoane thAccounts.RoomNumberCamera principală Ca plat, personal personal.division.parent.description ca MRO din director.personalAccounts as PersonalAccounts au plecat de la Registrul de date. ", q) selectie = interogare.Execute().Choose() CONN = db.connect() CONN.query(models.Abonent).delete() while selection.Next(): abonent = modele.Abonent() abonent. cont = selectie.code.strip() abonent.code = selectie.cod abonent.fio = selectie.fio abonent.address = selectie.adresa abonent.psu = selectie.psu abonent.tso = selectie. tso abonent.source = u" ASRN" abonent.np = selectie.np abonent.street = selectie.strada abonent.house = selectie.casa abonent.flat = selectie.flat abonent.mro = selection.mro CONN.add(abonent) CONN.commit()

Aici CONN este sesiunea de conectare cu baza de date SQLite. Este creat un obiect de interogare, textul acestuia este umplut. După cum s-a menționat mai sus, textul solicitării trebuie să fie în cp1251, pentru care codificarea este mai întâi declarată. După ce interogarea este executată, toți abonații sunt șterși în baza de date pentru a nu adăuga duplicate, apoi sunt adăugați într-un ciclu și urmează commit-ul final.

Când lucram cu solicitări, am descoperit următoarele reguli.

Când selectați câmpuri, dați-le nume latine, va fi mult mai convenabil să le accesați printr-un selector (punct), în loc de getattr().
- Alegeți numai tipuri de date primitive: șiruri de caractere, numere, date și boolean. Nu selectați niciodată link-uri către un obiect (document, director)! În acest context, absolut nu aveți nevoie de referințe și sunt chiar dăunătoare, deoarece orice acces la atributul sau metoda referinței va avea ca rezultat o solicitare printr-o conexiune COM. Dacă accesați atributele linkului într-o buclă, va fi extrem de lent.
- Dacă selectați un câmp Data, acesta va fi returnat ca obiect PyTime. Acesta este un tip de date special pentru transmiterea datei/ora pe o conexiune COM. Nu este la fel de convenabil să lucrezi cu el ca la data și ora obișnuită. Dacă treceți acest obiect către int(), atunci va fi returnat un marcaj de timp, de la care puteți obține data și ora folosind metoda fromtimestamp().

Acum să vedem cum se formează documentele tipărite. Faptul este că consumatorului trebuie să i se ofere posibilitatea de a descărca documente pregătite în prealabil, de exemplu, o chitanță de plată sau un act de reconciliere. Aceste documente sunt generate în 1C în conformitate cu cerințele stabilite, implementarea lor în Python va dura mult timp. Prin urmare, este mai bine să generați documente în 1C și să le salvați în format Excel.

Deci, documentul actului de reconciliere este generat prin prelucrare externă specială. Pentru cei care nu sunt familiarizați cu terminologia 1C: procesarea este un program autonom care are propriul modul, formulare, șabloane, concepute pentru a rula în mediul 1C. Este necesar să inițializam procesarea, să completam detaliile acesteia și să apelăm la o funcție care ne va returna un document foaie de calcul destinat vizualizării în 1C. Acest document trebuie salvat în format Excel și copiat pe server sau scris în baza de date.

Link = getattr(V82.Catalogs, "SystemReports").FindByDescription("Elen's Verification Act") nav_url = V82.GetURL(link, "Report") name = V82.ExternalReports.Connect(nav_url) ExternalReport = V82.ExternalReport (nume) setattr(ExternalReport, "PersonalAccount", referință) table_doc = ExternalReport.GetDoc() cale = V82.GetTempFileName("xls") table_doc.Write(path, V82 .SpreadsheetDocumentFileType.XLS) raport = modele.Raport() raport .account = reference.Code.strip() report.type = u"act" report.document = open(cale, "rb").read() CONN.add(raport)

Fragmentul de mai sus face următoarele. Procesarea care formează documentul este conectată. Procesarea poate fi încorporată în configurație, stocată pe disc sau într-o bază de date 1C (într-un fel de director). Deoarece procesarea se modifică frecvent, pentru a nu actualiza configurația de fiecare dată, procesarea care se schimbă cel mai frecvent este stocată în directorul „ReportsSystem”, în atributul tipului „stocare valori” cu numele Raport. Procesarea poate fi inițializată prin descărcarea acesteia din baza de date pe disc și încărcarea acesteia, sau prin metoda GetURL(), în care trebuie să treceți un link către elementul director și numele atributului. Atribuim valori de atribut obiectului de procesare rezultat, apelăm funcția GetDoc() exportată și obținem un document foaie de calcul care este salvat într-un fișier Excel temporar. Conținutul acestui fișier este scris în baza de date SQLlite.

Ultimul lucru care rămâne de luat în considerare este introducerea programatică a datelor în 1C. Să presupunem că este necesar să introduceți indicații de la abonați. Pentru a face acest lucru, este suficient să creați și să conduceți documentul „Act de obținere a probelor”:

#coding=cp1251 acts = getattr(V82.Documente, „Act de luare mărturii”) act = acts.CreateDocument() setattr(act, „Indicație”, 1024.23) setattr(act, „Abonat”, „Ivanov”) # Completare în alte detalii...act.Write()
Acum introducerea datelor este automatizată.

Deci, am subliniat o metodă care se bazează pe încărcarea și descărcarea de date în mod programatic folosind o conexiune COM. Această metodă funcționează cu succes în organizația mea de aproape un an. Baza, formată din 1C, deservește 3 sisteme de plată, Internet acquiring (plată prin carduri prin Internet), precum și un cont personal. În plus, diferite scripturi sunt conectate la baza de date pentru a automatiza rutina.

În ciuda deficiențelor metodei (viteza lentă a conexiunii COM), în general, funcționează stabil. Avem date într-o formă independentă de platformă (SQLite) cu care se poate lucra din orice limbă. Și partea principală a codului este scrisă în Python, ceea ce înseamnă că sunt disponibile multe instrumente și tehnici la care nici nu le poți visa în 1C.

Acesta este unul dintre moduri posibile interacțiunea cu 1C. Sunt sigur că nu este nou și probabil că a fost deja testat și optimizat de cineva. Cu toate acestea, am încercat să expun cât mai multe detalii ale procesului pentru a vă salva de capcanele pe care am călcat eu însumi.

Vă doresc tuturor noroc și amintiți-vă că 1C nu este atât de înfricoșător pe cât este pictat!