Microsoft Power Apps is a low-code development platform that enables you to build custom apps tailored to your business needs. Within Power Apps, a 'Canvas App' is a specific type of app that allows you to design your interface by dragging and dropping elements onto a canvas, similar to designing a slide in PowerPoint. While Canvas Apps do not natively support the embedding or execution of JavaScript code, they do allow for the invocation of services through Power Automate (Flow). This article aims to assist developers in integrating document scanning functionalities into Power Apps Canvas by utilizing the Dynamsoft Service REST API.
Pre-requisites
- Dynamsoft Service REST Preview for Windows: Download and install Dynamsoft Service on your Windows machine.
- 30-day Free Trial License: Get a free trial license for Dynamsoft Service.
- Ngrok (optional): Download and install Ngrok to expose your local web server to the Internet.
Setting Up a Web Server for Communication with the Dynamsoft Service
Dynamsoft Service is designed to operate within a local network via HTTP requests. To make it accessible from the Internet, a web server needs to be set up to forward requests to Dynamsoft Service.
For a quick setup, you can download example code from the following GitHub repository: https://github.com/yushulx/dynamsoft-service-REST-API/tree/main/examples/REST.
To run the example code:
- Install Node.js.
-
Open
app.js
and replace the license key with your own.
license: "LICENSE-KEY",
-
open a terminal and run the following commands:
npm install node app.js > Server running at http://0.0.0.0:3000/
-
Use ngrok to expose the local web server to the Internet.
ngrok http 3000
-
Visit the ngrok URL in a browser to verify that the web server is running properly.
Building a Document Scanning App with Power Apps Canvas
Step 1: Create a Blank Canvas App
Visit https://make.powerapps.com/ to create a Blank Canvas App
.
Step2: Add UI Elements
The UI consists of two buttons, a dropdown list, and an image control.
- The
Get Devices
button triggers an HTTP GET request to retrieve a list of available scanners. - The dropdown list displays the list of available scanners.
- The
Scan
triggers an HTTP POST request to initiate document scanning. - The image control displays the scanned image.
Step3: Create Power Automate Flows
According to our requirements, we create two flows: ScanDocument
and GetDevices
in Power Automate panel.
Power Automate Flow for HTTP GET
The GetDevices
flow consists of four operations: HTTP
, Parse JSON
, Select
, and Response
.
HTTP
Send an HTTP GET request to the web server. The URL is constructed with the ngrok URL and the /devices
path.
Parse JSON
Parse the response body as JSON to extract the device information.
The schema of the JSON response is as follows:
{
"type": "object",
"properties": {
"devices": {
"type": "array",
"items": {
"type": "object",
"properties": {
"device": {
"type": "string"
},
"name": {
"type": "string"
},
"type": {
"type": "integer"
}
},
"required": [
"device",
"name",
"type"
]
}
}
}
}
It can be automatically generated from the example response body:
{"devices":[{"device":"{\n\t\"deviceInfo\" : \n\t{\n\t\t\"Manufacturer\" : \"VFdBSU4gV29ya2luZyBHcm91cA==\",\n\t\t\"ProductFamily\" : \"U29mdHdhcmUgU2Nhbg==\",\n\t\t\"ProductName\" : \"V2luZG93cyBWaXJ0dWFsIFNjYW5uZXI=\",\n\t\t\"ProtocolMajor\" : 2,\n\t\t\"ProtocolMinor\" : 5,\n\t\t\"SupportedGroups\" : 0,\n\t\t\"Version\" : \n\t\t{\n\t\t\t\"Country\" : 1,\n\t\t\t\"Info\" : \"Mi41LjAgc2FtcGxlIHJlbGVhc2UgNjRiaXQ=\",\n\t\t\t\"Language\" : 2,\n\t\t\t\"MajorNum\" : 2,\n\t\t\t\"MinorNum\" : 5\n\t\t}\n\t},\n\t\"deviceType\" : 64,\n\t\"isSystemDefaultPrinter\" : false,\n\t\"name\" : \"V2luZG93cyBWaXJ0dWFsIFNjYW5uZXI=\"\n}\n","name":"Windows Virtual Scanner","type":64},{"device":"{\n\t\"deviceInfo\" : \n\t{\n\t\t\"BaudRate\" : \"\",\n\t\t\"Description\" : \"WSD Scan Device\",\n\t\t\"Driver Version\" : \"10.0.19041.1806\",\n\t\t\"Hardware Configuration\" : 0,\n\t\t\"Manufacturer\" : \"Microsoft\",\n\t\t\"Name\" : \"HPBCF77F (HP LaserJet Pro M329)\",\n\t\t\"PnP ID String\" : \"\\\\\\\\?\\\\swd#dafwsdprovider#urn:uuid:f8262726-dc64-5cf1-89ab-5e257f2d0f3a#http:##f8262726-dc64-5cf1-89ab-5e257f2d0f3a#scanservice#{6bdd1fc6-810f-11d0-bec7-08002be2092f}\",\n\t\t\"Port\" : \"urn:uuid:f8262726-dc64-5cf1-89ab-5e257f2d0f3a/http://f8262726-dc64-5cf1-89ab-5e257f2d0f3a/ScanService\",\n\t\t\"Remote Device ID\" : \"\",\n\t\t\"STI Driver Version\" : 3,\n\t\t\"STI Generic Capabilities\" : 49,\n\t\t\"Server\" : \"local\",\n\t\t\"Type\" : 65537,\n\t\t\"UI Class ID\" : \"{00000000-0000-0000-0000-000000000000}\",\n\t\t\"Unique Device ID\" : \"{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}\\\\0000\",\n\t\t\"WIA Version\" : \"2.0\"\n\t},\n\t\"deviceType\" : 32,\n\t\"isSystemDefaultPrinter\" : true,\n\t\"name\" : \"SFBCQ0Y3N0YgKEhQIExhc2VySmV0IFBybyBNMzI5KQ==\"\n}\n","name":"HPBCF77F (HP LaserJet Pro M329)","type":32},{"device":"{\n\t\"deviceInfo\" : \n\t{\n\t\t\"BaudRate\" : \"\",\n\t\t\"Description\" : \"HP OfficeJet Pro 6970 [01A3B2]\",\n\t\t\"Driver Version\" : \"10.0.19041.3271\",\n\t\t\"Hardware Configuration\" : 0,\n\t\t\"Manufacturer\" : \"Microsoft\",\n\t\t\"Name\" : \"HP OfficeJet Pro 6970 [01A3B2]\",\n\t\t\"PnP ID String\" : \"\\\\\\\\?\\\\swd#escl#59ca18cd-afb6-5c82-a201-23911ae167ea#{6bdd1fc6-810f-11d0-bec7-08002be2092f}\",\n\t\t\"Port\" : \"SWD\\\\Escl\\\\59ca18cd-afb6-5c82-a201-23911ae167ea\",\n\t\t\"Remote Device ID\" : \"\",\n\t\t\"STI Driver Version\" : 16777218,\n\t\t\"STI Generic Capabilities\" : 16,\n\t\t\"Server\" : \"local\",\n\t\t\"Type\" : 65537,\n\t\t\"UI Class ID\" : \"{00000000-0000-0000-0000-000000000000}\",\n\t\t\"Unique Device ID\" : \"SWD\\\\Escl\\\\59ca18cd-afb6-5c82-a201-23911ae167ea\",\n\t\t\"WIA Version\" : \"2.0\"\n\t},\n\t\"deviceType\" : 32,\n\t\"isSystemDefaultPrinter\" : false,\n\t\"name\" : \"SFAgT2ZmaWNlSmV0IFBybyA2OTcwIFswMUEzQjJd\"\n}\n","name":"HP OfficeJet Pro 6970 [01A3B2]","type":32},{"device":"{\n\t\"deviceInfo\" : \n\t{\n\t\t\"UUID\" : \"f8262726-dc64-5cf1-89ab-5e257f2d0f3a\",\n\t\t\"adminurl\" : \"http://HP6C02E0BCF77F.local.\",\n\t\t\"cs\" : \"binary,color,grayscale\",\n\t\t\"duplex\" : \"F\",\n\t\t\"is\" : \"platen,adf\",\n\t\t\"mopria-certified-scan\" : \"1.2\",\n\t\t\"name\" : \"HP LaserJet Pro M329 [BCF77F]\",\n\t\t\"pdl\" : \"application/octet-stream,application/pdf,image/jpeg\",\n\t\t\"representation\" : \"images/printer.png\",\n\t\t\"rs\" : \"eSCL\",\n\t\t\"service_type\" : 3,\n\t\t\"txtvers\" : \"1\",\n\t\t\"ty\" : \"HP LaserJet Pro M329\",\n\t\t\"vers\" : \"2.63\"\n\t},\n\t\"deviceType\" : 512,\n\t\"name\" : \"SFAgTGFzZXJKZXQgUHJvIE0zMjk=\"\n}\n","name":"HP LaserJet Pro M329","type":512}]}
Select
This operation extracts device information from the JSON object as the output.
Response
Send the select output back to the Power App.
Power Automate Flow for HTTP POST
The ScanDocument
flow consists of four operations: Compose
, HTTP
, Parse JSON
, and Return value(s) to Power Pages
.
Compose
Input the selected scanner information from the Power App page.
HTTP
Append the compose output to the HTTP body and send an HTTP POST request to the web server. The URL is constructed with the ngrok URL and the /scandocument
path.
Parse JSON
Parse the response body as JSON to extract the scanned image.
The schema of the JSON response is as follows:
{
"type": "object",
"properties": {
"image": {
"type": "string"
}
}
}
Return value(s) to Power Pages
Return the image name to the Power App page.
Step4: Connect Power Automate Flows to the UI Elements
Get devices
Click on the Get Devices
button and then assign the following code to its OnSelect
property.
ClearCollect( Devices, GetDevices.Run());
The code above will initiate the GetDevices
flow when the Get Devices
button is clicked. The flow's response will populate the Devices
collection, which can be found in the Variables
panel.
Display device list
Click on the dropdown list and then assign Devices
collection to its Items
property. Then, set the display value to name
in the properties panel.
Acquire a document image
Click on the Scan
button and then assign the following code to its OnSelect
property.
Set(jsonString, Concatenate("{", """scan""", ":", DeviceList.Selected.Device, "}"));
Set(data, ScanDocument.Run(jsonString));
The code constructs a JSON string with the selected scanner information and then initiates the ScanDocument
flow. The data
variable will be populated with the response from the flow and can be found in the Variables
panel.
Display the document image
Set the Image
property using the URL of the scanned image. The URL is constructed by combining the ngrok URL with the image name.