5640x
001738
2022-03-23

Webservice API w tutorialu VBA

Webservice to komunikacja między maszynami i programami. Komunikacja ta odbywa się za pośrednictwem sieci i dlatego może być wykorzystywana przez dowolny program, który może wysyłać i odbierać ciągi znaków za pośrednictwem protokołu HTTP. Programy RFEM 6 i RSTAB 9 zapewniają interfejs oparty na tych wieloplatformowych usługach sieciowych. Ten tutorial pokazuje podstawy korzystania z języka programowania VBA.

Podstawy Webservice API na przykładzie VBA

Do formatowania łańcucha używany jest format XML zgodnie ze specyfikacją protokołu SOAP. Za przykład może posłużyć poniższe zapytanie:

<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Bryła>
<get_active_model xmlns="http://www.dlubal.com/rfem.xsd"/>
</Body>
</Envelope>

Typowym elementem formatowania XML jest początek sekcji od znaku „<”. Po nim następuje oznaczenie, aw przypadku braku dalszych elementów podrzędnych, przekrój kończy się za pomocą "/>". Jednym z przykładów jest trzecia linia:

<get_active_model xmlns="http://www.dlubal.com/rfem.xsd"/>

Jeżeli występują elementy podrzędne, to zaczyna się on na "<", komenda i ">", a kończy na "</", komenda i ">". Odpowiednim przykładem jest sekcja "Body":

<Bryła>
<get_active_model xmlns="http://www.dlubal.com/rfem.xsd"/>
</Body>

Formatowanie ze spacjami i końcami linii zostało tutaj użyte wyłącznie w celach ilustracyjnych. Nie jest to wymagane w przypadku transferu. Elementy "Bryła" i "Obwiednia" są standardowymi elementami do przenoszenia i są używane w każdym poleceniu.

Wszystkie dostępne polecenia można odczytać za pomocą interfejsu WSDL. Dostępne jest oprogramowanie, za pomocą którego można tworzyć zestawienia. Przykładem takiego oprogramowania jest SoapUI. Interfejs API programu RFEM 6 zawiera dwie listy; polecenia dla aplikacji i dla modelu. Obie listy można pobrać na końcu tego artykułu.

Ponieważ polecenia są wysyłane za pośrednictwem protokołu HTTP, do adresowania wymagane są adresy URL. Domyślny adres aplikacji RSTAB/RFEM to "http://localhost:8081/" i można go zmienić w ustawieniach programu. Otwieranym modelom przypisywane są adresy w kolejności rosnącej, dzięki czemu pierwszy otwarty model ma adres "http://localhost:8082/". Aby uzyskać adres aktywnego modelu, wysyłane jest polecenie "get_active_model". Odpowiednia odpowiedź z programu RFEM 6 wygląda następująco:

<?xml version="1.0"?>
<Koperta xmlns:soap="http://schemas.xmlsoap.org/soap/koperta/"
xmlns:soap-enc="http://schemas.xmlsoap.org/soap/kodowanie/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSwystąpienie-schematu">
<mydło:Ciało>
<n1:get_active_modelResponse
xmlns:n1="http://www.dlubal.com/rfem.xsd">
<wartość>
http://127.0.0.1:8082/
</value>
</n1:get_active_modelResponse>
</soap:Body>
</soap:Envelope>

Dodatkowe informacje w sekcji „Koperta” podobnie jak w poprzednim wierszu "<?xml version="1.0"?>" powinien najpierw wskazywać użyte normy i nie będzie dalej omawiany. W każdym razie widać, że elementy "Envelope" i "Body" są ponownie używane. Odpowiedź w programie RFEM 6 jest zawarta w polu „Body” pod nazwą „get_active_model” i dołączonym słowem „Odpowiedź”. Treścią tej odpowiedzi jest „wartość”, a mianowicie adres aktywnego modelu. Ponadto program RFEM jest teraz zablokowany dla dalszego dostępu.

W poniższym przykładzie chcemy utworzyć pręt z dwoma podporami węzłowymi i obciążeniem. Aby móc komunikować się z programem RFEM za pośrednictwem VBA, wymagane są następujące obiekty:

zapytanie As MSXML2.XMLHTTP60
odpowiedź As MSXML2.DOMDocument

Obiekt XMLHTTP60 ma wbudowaną funkcję wysyłania żądania HTTP na adres URL i dlatego jest używany w żądaniu. Odpowiedź można następnie przeanalizować za pomocą DOMDocument. Poniższy przykład łączy pokazane wcześniej żądanie "get_active_model" z poleceniami używanymi w VBA:

' pobranie adresu URL aktywnego modelu za pomocą polecenia "get_active_model"
str_envelope =
"<Koperta xmlns=""http://schemas.xmlsoap.org/soap/koperta/"">" & _
" <Bryła>" & _
" <get_active_model xmlns=""http://www.dlubal.com/rfem.xsd""/>" & _
" </Body>" & _
"</Koperta>"

' otwórz żądanie i wyślij
request.Open "Post", "http://localhost:8081/", False
request.Send (str_envelope)

' pobierz odpowiedź i przekształć ją w obiekt xml
response.LoadXML (request.responseText)

Najpierw zapytanie jest zapisywane w formacie XML w zmiennej "str_envelope" i otwierane w programie RFEM przy użyciu metody "Open" zmiennej "request". Zawartość zmiennej "str_envelope" można teraz wysłać przy użyciu metody "Send". Dostęp do odpowiedzi można uzyskać za pomocą metody "ResponseText". W tym konkretnym przypadku jest to importowane bezpośrednio przy użyciu metody "LoadXML" zmiennej "response".

Zmienna "response" typu DOMDocuments posiada metodę LoadXML i dzięki temu może rozpoznać formatowanie XML. Zaletą jest to, że typ DOMDocuments udostępnia również metodę GetElementsByTagName. Pozwala to na wyodrębnienie elementów bezpośrednio z kodu. Poniżej poprzedni kod został rozszerzony w taki sposób, że dostępny jest adres URL modelu:

' pobierz stan-http
status = zapytanie.status
Jeżeli stan <> "200" Wtedy
MsgBox "get_active_model: Wysyłanie nie powiodło się - " & response.Text
Zakończ Sub
End If

url_model = response.GetElementsByTagName("value")(0).Text

Przed odczytaniem adresu URL można sprawdzić stan odpowiedzi. Są to znormalizowane kody stanu HTTP. Status "200" oznacza, że przelew był "OK". Po tym zapytaniu adres URL modelu jest zapisywany w ciągu url_model. W tym celu w odpowiedzi XML szukany jest element "value". Jeżeli odpowiedź zawiera kilka elementów, wszystkie wartości są zapisywane w sekcji "wartość", dzięki czemu nie jest możliwe obliczenie za pomocą identyfikatora "wartość", ale podelementy z "wartość" są adresowane. Więcej informacji zostanie podanych w przykładzie praktycznym. W przypadku adresu modelu jedyną zwracaną wartością jest adres URL, więc tutaj "wartość" jest pomyślna.

Praktyczny przykład w VBA

Teraz, gdy znamy wszystkie podstawowe elementy, następuje prosty przykład. Chcemy utworzyć belkę na dwóch słupach, do której można przyłożyć obciążenie prętowe.

W pierwszej kolejności definiowane i inicjalizowane są zmienne opisane powyżej:

' zdefiniuj zmienne
Żądanie wymiar. As MSXML2.XMLHTTP60
Odpowiedź dim As MSXML2.DOMDocument60

Dim str_envelope As String
Dim url_app As String
Dim model_url jako ciąg

' zmienne początkowe
Ustaw żądanie = Nowy MSXML2.XMLHTTP60

Ustaw odpowiedź = Nowy MSXML2.DOMDocument60
Z odpowiedzią
.async = Fałsz
.preserveWhiteSpace = False
.validateOnParse = False
.resolveExternals = False
' Użyj pełnej funkcjonalności XPath
.SetProperty "SelectionLanguage", "XPath"
' Dodaj określone przestrzenie nazw do pracy ze ścieżkami
.SetProperty "SelectionNamespaces", "xmlns:soap=""http://www.w3.org/2003/05/soap-envelope"" " & _
"xmlns:xsd=""http://www.dlubal.com/rfem.xsd"" " & _
"xmlns:n1=""urn:schemas-microsoft-com:rowset"" " & _
"xmlns=""http://www.dlubal.com/rfem.xsd"" "
Zakończ na

url_app = "http://localhost:8081/"

Oprócz zmiennych "request" i "response" dla zapytania tworzony jest łańcuch znaków "str_envelope" oraz dla adresów aplikacji i modelu "url_app" i "url_model". Podczas inicjalizacji można przesłać znane specyfikacje protokołu SOAP w celu oceny formatowania XML odpowiedzi. Adres modelu zostanie pobrany później, ale należy podać adres wniosku. Jak już wspomniano, należy wprowadzić domyślny adres „http://localhost:8081/”.

Kolejnym krokiem jest przetestowanie połączenia z aplikacją. W tym teście standardowe informacje o aplikacji są odpytywane za pomocą polecenia "get_information":

' sprawdź adres URL aplikacji za pomocą polecenia "get_information"
str_envelope = "<Koperta xmlns=""http://schemas.xmlsoap.org/soap/envelope/"">" & _
" <Bryła>" & _
" <get_information xmlns=""http://www.dlubal.com/rfem.xsd""/>" & _
" </Body>" & _
"</Koperta>"

' otwórz żądanie i wyślij
request.Open "Post", url_app, False
request.Send (str_envelope)

' pobierz odpowiedź i przekształć ją w obiekt xml
response.LoadXML (request.responseText)

' pobierz stan-http
status = żądanie.Status
Jeżeli stan <> "200" Wtedy
MsgBox "get_information: Wysyłanie nie powiodło się - " & response.Text
Zakończ Sub
End If

' przeczytaj informacje o aplikacji
Dim str1 As String
łańcuch1 = ""
słowo1 = słowo1 i odpowiedź.GetElementsByTagName("nazwa")(0).Text & vbLf
słowo1 = słowo1 i odpowiedź.GetElementsByTagName("type")(0).Text & vbLf
słowo1 = słowo1 i odpowiedź.GetElementsByTagName("wersja")(0).Text & vbLf
słowo1 = słowo1 i odpowiedź.GetElementsByTagName("nazwa_języka")(0).Text & vbLf
słowo1 = słowo1 i odpowiedź.GetElementsByTagName("identyfikator_języka")(0).Text

MsgBox str1, vbInformation, "Odpowiedź na żądanie ""pobierz_informacje"""

Jak już opisano w pierwszej części, żądanie w formacie XML jest przygotowywane i zapisywane w "str_envelope". "request.Open" otwiera połączenie z aplikacją. Słowo kluczowe "Post" oznacza wysłanie zapytania. Trzeci parametr zostaje ustawiony na „prawda” i tym samym realizowana jest transmisja synchroniczna. Na koniec "request.Send" wysyła przygotowany ciąg.

Po wysłaniu odpowiedź jest zapisywana w "odpowiedzi" i sprawdzana przy pomocy "żądanie.Status", czy żądanie się powiodło. Status jest nadawany przez program RFEM, dzięki czemu w przypadku nieprawidłowego żądania zwracany jest błąd; na przykład nieznane polecenie. Jeżeli status jest inny niż "200", program zostanie przerwany, a błąd zostanie wyświetlony w oknie (MsgBox).

Jeżeli nie wystąpiły żadne błędy, różne przesłane informacje można teraz odczytać za pomocą funkcji „GetElementsByTagName”. W konkretnym przykładzie informacje są następnie wyświetlane w oknie.

Poniższe elementy są bardzo podobne, więc opisane są tylko specjalne funkcje (można pobrać kompletny kod źródłowy). Aby ustawić belkę na dwóch słupach obciążonych prętem, wymagane są następujące funkcje:

  1. Węzeł - zbiór_węzeł
  2. Linia - zbiór_linii
  3. Materiał - zbiór_materiału
  4. Przekrój - zbiór_przekrój
  5. Pręt - pręt_zbiorowy
  6. Podpora węzłowa - set_nodal_support
  7. Parametry obliczeń - zestaw_ustawienia_analizy_statycznej
  8. Przypadek obciążenia - set_load_case
  9. Obciążenie pręta - obciążenie_zbioru_zbiorowego

Jak większość innych funkcji, funkcja "set_node" ma wiele parametrów, ale zazwyczaj nie są one wymagane. We wspomnianej już liście poleceń modelu w RFEM można zobaczyć różnorodność parametrów. Przede wszystkim ważne są parametry, które nie są oznaczone jako „opcjonalne”, ponieważ należy je w każdym przypadku uzupełnić. W tym przykładzie przenoszone są następujące parametry:

begin_modification (url_model)

' ustawić węzeł 1 na [0,0,0] za pomocą polecenia "set_node"
str_envelope =
"<Koperta xmlns=""http://schemas.xmlsoap.org/soap/koperta/"">" & _
"<Bryła>" & _
"<set_node xmlns=""http://www.dlubal.com/rfem.xsd"">" & _
"<value xmlns="""">" & _
"<no>1</no>" & _
"<type>TYPE_STANDARD</type>" & _
"<współrzędna_1>0</współrzędna_1>" & _
"<współrzędna_2>0</współrzędna_2>" & _
"<współrzędna_3>0</współrzędna_3>" & _
"</value>" & _
"</set_node>" & _
"</Body>" & _
"</Koperta>"

Tylko numer węzła nie jest opcjonalny; resztę można przypisać, ale nie musi. Na liście poleceń oprócz możliwych parametrów wyświetlane są również zestawienia typów. W tym konkretnym przypadku dostępnych jest obecnie pięć różnych typów. Wybrano domyślny typ "TYPE_STANDARD". Pokazany tutaj pierwszy węzeł jest tworzony w położeniu (0; 0; 0), drugi węzeł w położeniu (5,5; 0; 0). Wartości liczb dziesiętnych są następujące:

...
"<value xmlns="""">" & _
"<no>2</no>" & _
"<type>TYPE_STANDARD</type>" & _
"<współrzędna_1>5,5</współrzędna_1>" & _
"<współrzędna_2>0</współrzędna_2>" & _
"<współrzędna_3>0</współrzędna_3>" & _
"</value>" & _
...

Kolejną cechą szczególną są listy. Linia wymaga dwóch węzłów, których numery można przenieść w formie listy. Elementy listy, takie jak "definition_nodes", są oddzielone spacjami:

...
"<set_line xmlns=""http://www.dlubal.com/rfem.xsd"">" & _
"<value xmlns="""">" & _
"<no>1</no>" & _
"<type>TYPE_POLYLINE</type>" & _
"<definition_nodes>1 2</definition_nodes>" & _
"</value>" & _
"</set_line>" & _
...

Aby móc utworzyć pręt, należy utworzyć przekrój, który z kolei wymaga materiału. Przekroje i materiały można wykorzystywać z wewnętrznej bazy danych. Dlatego wystarczy podać znany identyfikator. Dla materiału identyfikator to "S235", a przekrój ma nazwę "IPE 300":

...
"<set_section xmlns=""http://www.dlubal.com/rfem.xsd"">" & _
"<value xmlns="""">" & _
"<no>1</no>" & _
"<material>1</material>" & _
"<type>TYPE_STANDARDIZED_STEEL</type>" & _
"<name>IPE 300</name>" & _
"</value>" & _
"</set_section>" & _
...

Aby sprawdzić, czy nazwa taka jak "IPE 300" jest prawidłowa, można użyć wpisu w graficznym interfejsie użytkownika.

Aby wprowadzić sam pręt, nie jest wymagana szczególna wiedza, ale aby wprowadzić nieruchomą podporę, należy zdefiniować "nieskończoną" sztywność sprężystą. Do przelewu używane jest słowo kluczowe "INF":

...
"<set_nodal_support xmlns=""http://www.dlubal.com/rfem.xsd"">" & _
"<value xmlns="""">" & _
"<no>1</no>" & _
"<nodes>1</nodes>" & _
"<spring_x>INF</spring_x>" & _
"<spring_y>INF</spring_y>" & _
"<spring_z>INF</spring_z>" & _
"<obrotowe_ograniczenie_x>INF</obrotowe_ograniczenie_x>" & _
"<rotational_restraint_y>0</rotational_restraint_y>" & _
"<rotational_restraint_z>INF</rotational_restraint_z>" & _
"</value>" & _
"</set_nodal_support>" & _
...

Tworzenie przypadku obciążenia i parametrów obliczeniowych nie wymaga dodatkowej wiedzy. Ostatnia osobliwość jest wartością dodatkową podczas tworzenia obciążenia, ponieważ musi zostać określona poza obszarem "<wartość>". W przypadku obciążenia prętowego należy tam przenieść odpowiedni przypadek obciążenia:

...
"<set_member_load xmlns=""http://www.dlubal.com/rfem.xsd"">" & _
"<load_case_no xmlns="""">1</load_case_no>" & _
"<value xmlns="""">" & _
"<no>1</no>" & _
"<load_type>LOAD_TYPE_FORCE</load_type>" & _
"<członkowie>1</członkowie>" & _
"<load_distribution>LOAD_DISTRIBUTION_UNIFORM</load_distribution>" & _
"<load_direction>LOAD_DIRECTION_GLOBAL_Z_OR_USER_DEFINED_W_TRUE</load_direction>" & _
"<magnitude>1000</magnitude>" & _
"</value>" & _
"</set_member_load>" & _
...

Ponadto należy wspomnieć, że kolejność elementów w obszarze „wartość” jest nieistotna, ale poza nią nie ma znaczenia. Określony przypadek obciążenia musi zatem znajdować się przed obszarem „wartość”.

Oprócz poprzednich funkcji tworzenia i eksportowania danych, zostaną tu pokazane dwie funkcje specjalne. Jeżeli elementy zostaną przeniesione do programu, program automatycznie przechodzi w tryb "Modyfikacja". Program sprawdza nowe elementy i integruje je. Jeżeli ma zostać utworzonych kilka nowych elementów, warto na ten czas pozostawić program w tym trybie edycji, aby przyspieszyć obróbkę. W tym celu dostępne są funkcje "begin_modification" i "finish_modification". W tym przykładzie, "begin_modification" jest wywoływane przed utworzeniem pierwszego węzła, a "finish_modification" jest wywoływane na końcu po utworzeniu przypadku obciążenia. Obie funkcje zostały również utworzone w programie jako funkcje VBA. Funkcje są niezależne, dlatego też zmienne "request" i "response" są ponownie tworzone w obrębie funkcji. Ponieważ jednak nie są do tego potrzebne żadne nowe elementy, nie będą one tutaj dalej opisywane. Ciekawym porównaniem jest porównanie z użyciem tych funkcji i bez nich, które zawsze spowoduje różnicę prędkości.

Podsumowanie

Webservice API to wydajne narzędzie dla programów RFEM i RSTAB. Prosty transfer oparty na HTTP umożliwia implementację interfejsu w wielu językach programowania, nie tylko w VBA, jak pokazano tutaj, i umożliwia programowanie międzyplatformowe.


Autor

Pan Günthel zapewnia wsparcie techniczne klientom firmy Dlubal Software i zajmuje się ich zapytaniami.

Odnośniki
Pobrane