PowerApps+Flow logo

Klient zapytał mnie, czy jest możliwe, by wstawić ręczny podpis do pliku PDF generowanego wyłącznie z użyciem narzędzi dostępnych w Office 365. Moja pierwsza myśl była „nie”. Potem sprawdziłem, że istnieje pole o nazwie „Pen input”, a myśl zmieniła się na „tak”. Potem zacząłem próbować i szukać wskazówek jak to można zrobić i znów pojawiła się myśl „nie, nie da się”.

Dlaczego?

Otóż dlatego, że zachowanie kontrolki „Pen input” jest daleko różne, od powszechnie omawianego w community pola „Camera”: dane z tego pola nie są przechowywane w postaci ciągu znaków zakodowanych do base64, ale jako hiperłącze do lokalnego blob storage (appres://blobmanager/), który jest dostępny wyłącznie dla bieżącej instancji aplikacji.

Pole "Pen input" w PowerApps
Pole „Pen input” w PowerApps

Tym samym gdy próbowałem przekazać wartość z pola do Microsoft Flow, proces nie był w stanie znaleźć obrazu z podpisem, ponieważ otrzymywał wyłącznie nic niemówiący adres URL, co skutkowało pojawianiem się różnych błędów, np.:

Błąd powiązany ze złym formatem danych
Błąd powiązany ze złym formatem danych

Rozwiązania

Moje ogólne założenie było takie, by nie korzystać z rozwiązań firm trzecich i nie uciekać się np. do Azure Functions. Również, by zrobić to rozwiązanie tak prosto, jak to tylko możliwe. Przeglądając fora i materiały w internecie natrafiłem w zasadzie na 3 ciekawe rozwiązania tego problemu:

  1. Sugerujące, by obrazy podpisów zapisywać do kolekcji następnie zapisywać je do SharePoint (https://powerusers.microsoft.com/t5/General-Discussion/Save-Signature-to-SharePoint-List/td-p/76661) – osobiście nie udało mi się tego rozwiązania uruchomić. Mimo zapisywania podpisów do kolekcji, podczas próby ich przeniesienia do SP nadal reprezentowane były przez hiperłącza do blobmanagera.
  2. Drugie było naprawdę ciekawe, opisujące rozwiązanie z użyciem connectora Outlook i wysyłania podpisu jako załącznika do maila (https://powerusers.microsoft.com/t5/Creating-Apps/PowerApps-Digital-Signature-to-Sharepoint-List/m-p/153702/highlight/true#M4252) – i to w zasadzie, ku memu wielkiemu zaskoczeniu, zadziałało – bo w zasadzie dlaczego wysłanie podpisu mailem tworzy z niego plik graficzny, a przekazanie go do Flow nie? 🙂
  3. To, najbardziej zaawansowane rozwiązanie, opisywało podejście wykorzystujące custom connector oparty na OpenAPI (https://powerusers.microsoft.com/t5/General-Discussion/Pen-input-save-image-to-SharePoint/m-p/82215/highlight/true#M31819) – tego rozwiązania nie zaimplementowałem, ale załączonoy film pokazuje, że działa.

W każdym razie, w mojej opinii, wymienione powyżej rozwiązania były albo zbyt skomplikowane, albo za mało stabilne. Np. rozwiązanie z mailem wymagało nawet do 5 minut czekania, by Flow wyzwalany nową wiadomością uruchomił się.

Moje rozwiązanie

Generalnie celem aplikacji było dostarczenie pracownikom terenowym narzędzia, dzięki któremu mogliby wypełniać raporty inspekcji i podpisywać je bezpośrednio na urządzeniu, te zaś byłyby zapisywane do SharePoint w postaci PDF, by brać udział w procesach zatwierdzania. Dla swoich potrzeb zdecydowałem się na wykorzystanie Azure Blob Storage, jako kontenera do przechowywania zapisanych podpisów i ich późniejszego wykorzystania w generowanych dokumentach. Sam proces wygląda następująco:

  1. Użytkownik wypełnia formularz
  2. Użytkownik podpisuje formularz
  3. Formularz jest wysyłany do SharePoint
  4. W zdarzeniu”OnSuccess” formularza znajdują się akcje zapisujące obraz podpisu do Blob Storage i następnie wyzwalające przepływ Flow, przekazując dane wejściowe z wysłanego formularza.
  5. Microsoft Flow pobiera plik podpisu i wstawia do pliku HTML.
  6. Następnie konwertuje plik HTML do PDF
  7. Na koniec dołącza wygenerowany PDF do elementu w SharePoint utworzonego w kroku 3.

Tworzenie blob storage

Usługa blob storage jest niedroga. Uważam, że mój klient, wobec spodziewanego użycia, będzie płacić dosłownie „0” (https://azure.microsoft.com/en-us/pricing/details/storage/blobs/). By stworzyć taką usługę, przejdź do portalu Azure i utwórz nowe konto „storage”:

Tworznie konta "Storage"
Tworznie konta „Storage” w Azure Portal

Gdy je utworzysz, otwórz dashboard usługi i przejdź do pozycji „Storage Explorer” i utwórz nowy kontener blob:

Tworzenie nowego kontenera blob w Azure Portal
Tworzenie nowego kontenera blob w Azure Portal

P.S. W tym celu możesz również użyć bezpłatnej, desktopowej aplikacji od Microsoft nazywającej się „Azure Storage Explorer” (https://azure.microsoft.com/en-us/features/storage-explorer/).

Tworzenie aplikacji PowerApp

Następnie utwórz aplikację w PowerApps. Dodaj kontrolkę „Pen input”. I przycisk „Submit”. Dodaj także nowe źródło danych, którym będzie „Azure Blob Storage”. Gdy będziesz je tworzyć, zostaniesz poproszony o podanie Azure Storage account name i account access key:

Wymagane dane dla utworzenia połączenia do źródła danych Azure Blob Storage w PowerApps
Wymagane dane dla utworzenia połączenia do źródła danych Azure Blob Storage w PowerApps

Te dane możesz odczytać ponownie wchodząc na dashboard usługi i tym razem otwierając pozycję menu „Access key”:

Azure Blob Storage name i access keys
Azure Blob Storage name i access keys

Skopiuj jeden z kluczy i nazwę do formularza dodawania źródła danych w PowerApps.

Teraz, dla przycisku możesz dodać nową funkcję, która będzie tworzyć plik na koncie blob storage:

AzureBlobStorage.CreateFile("files", "TestFile.png", PenInput1.Image);

Gdzie:

  • „files” – to jest nazwa utworzonego „blob container”
  • „TestFile.png” – nazwa pliku, który będzie zawierać podpis pobrany z pola „Pen input”.
  • PenInput1.Image – zawartość obrazu, który zostanie zapisany jako plik.

Microsoft Flow

Następnie konieczne jest uworzenie przepływu Microsoft Flow, który będzie łączyć dane z przesłanego formularza i obraz zawierający podpis, do pliku HTML i następnie konwertować go do pliku PDF. Przepływ Microsoft Flow jest wyzwalany po zdarzeniu utworzenia pliku w blob storage – w moim przykładzie obie funkcje są wyzwalane na zdarzenie „OnSuccess” zapisu formularza, jednak rozdzielenie ich średnikiem powoduje, że druga nie uruchomi się, nim pierwsza się nie zakończy:

AzureBlobStorage.CreateFile("files", "TestFile.png", PenInput1.Image); SignDocument.Run(Form1.LastSubmit.Location, Form1.LastSubmit.Customer, Form1.LastSubmit.ReportComments, User().FullName, "/files/TestFile.png", Form1.LastSubmit.ID);ResetForm(Form1);Reset(PenInput1)

Ścieżka „/files/TestFile.png” przekazana jako parametr wskazuje na plik i lokalizację w blob storage, którą wykorzystuję w Microsoft Flow, w akcji „Get blob content”. Po pobraniu obrazu, tworzony jest kod HTML, do którego podpis wstawiany jest używając wyrażenia poniżej: 

<p><img width="200" src="@{dataUri(body('Get_blob_content'))}" /></p>

Następnie używam akcji „Create file” z zestawu „One Drive”, która tworzy plik HTML wykorzystując przygotowany wcześniej kod. Potem używam akcji do skonwertowania pliku HTML do PDF. Finalnie proces dołącza wygenerowany plik PDF jako załącznik do elementu na liście SharePoint, utworzonego przez zapis formluarza w aplikacji PowerApps. Identyfikator ID rekordu jest również przekazywany jako parametr:

Microsoft Flow użyty do dołączenia pliku PDF zawierającego podpis do elementu listy w SharePoint
Microsoft Flow użyty do dołączenia pliku PDF zawierającego podpis do elementu listy w SharePoint

Wynik

Przygotowany prood od concept spełnia doskonale stawiane przed nim oczekiwania i cele biznesowe. Sam zobacz!

Działające rozwiązanie

Proszę, zostaw swoje komentarze i pytania poniżej!

Dla porównania możesz też zobaczyć, jak podobne rozwiązanie można stworzyć z użyciem Nintex Forms: https://poszytek.eu/nintex/mobile/how-to-wykorzystanie-podpisu-z-nintex-mobile-w-document-generation/

Cześć! Nazywam się Tomasz. Jestem wielkim fanem automatyzacji procesów i analizy biznesowej. Skupiam się na rozwijaniu moich umiejętności w pracy z produktami Nintex i Microsoft: w szczególności Office 365, SharePoint, Flow, PowerApps. Posiadam ponad 8 lat doświadczenia w pracy z SharePoint.