Power Apps Dev: Integrating Document Scanning Functionality into Canvas App
Tags: powerapps, powerautomate, powerplatform, documentscan
Published: 2023-09-22 08:33:38

**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](https://www.dynamsoft.com/codepool/downloads/DynamsoftServiceSetup.msi): Download and install Dynamsoft Service on your Windows machine.
- [30-day Free Trial License](https://www.dynamsoft.com/customer/license/trialLicense?product=dwt&source=codepool): Get a free trial license for Dynamsoft Service.
- Ngrok (optional): [Download](https://ngrok.com/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](https://github.com/yushulx/dynamsoft-service-REST-API/tree/main/examples/REST). 


To run the example code:

1. Install [Node.js](https://nodejs.org/en/download/).
2. Open `app.js` and replace the license key with your own.
    
    ```json
    license: "LICENSE-KEY",
    ```

3. open a terminal and run the following commands:

    ```bash
    npm install
    node app.js
    > Server running at http://0.0.0.0:3000/
    ```
4. Use ngrok to expose the local web server to the Internet.

    ```bash
    ngrok http 3000
    ```
    ![ngrok](https://www.dynamsoft.com/codepool/img/2023/09/ngrok-https.png)

5. Visit the ngrok URL in a browser to verify that the web server is running properly.

    ![web server](https://www.dynamsoft.com/codepool/img/2023/09/web-server-document-scan.png)


## Building a Document Scanning App with Power Apps Canvas

### Step 1: Create a Blank Canvas App

Visit [https://make.powerapps.com/](https://make.powerapps.com/) to create a `Blank Canvas App`.

![Power App Canvas App](https://www.dynamsoft.com/codepool/img/2023/09/power-app-canvas-app.png)


### Step2: Add UI Elements
The UI consists of two buttons, a dropdown list, and an image control.

![Power App Canvas UI](https://www.dynamsoft.com/codepool/img/2023/09/power-app-canvas-ui.png)

- 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 flows](https://www.dynamsoft.com/codepool/img/2023/09/power-automate-flows.png)


#### Power Automate Flow for HTTP GET
The `GetDevices` flow consists of four operations: `HTTP`, `Parse JSON`, `Select`, and `Response`.

![GetDevices Flow](https://www.dynamsoft.com/codepool/img/2023/09/get-device-flow.png)

**HTTP**

Send an HTTP GET request to the web server. The URL is constructed with the ngrok URL and the `/devices` path.

![power automate HTTP Action](https://www.dynamsoft.com/codepool/img/2023/09/power-automate-http.png)


**Parse JSON**

Parse the response body as JSON to extract the device information.

![power automate parse JSON](https://www.dynamsoft.com/codepool/img/2023/09/power-automate-parse-json.png)

The schema of the JSON response is as follows:

```json
{
    "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:

```json
{"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.

![power automate select](https://www.dynamsoft.com/codepool/img/2023/09/power-automate-select.png)

**Response**

Send the select output back to the Power App.

![Power automate response](https://www.dynamsoft.com/codepool/img/2023/09/power-automate-response.png)


#### Power Automate Flow for HTTP POST
The `ScanDocument` flow consists of four operations: `Compose`, `HTTP`, `Parse JSON`, and `Return value(s) to Power Pages`.

![scan document flow](https://www.dynamsoft.com/codepool/img/2023/09/scan-document-flow.png)

**Compose**

Input the selected scanner information from the Power App page.

![power automate compose](https://www.dynamsoft.com/codepool/img/2023/09/power-automate-compose.png)

**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.

![power automate HTTP post](https://www.dynamsoft.com/codepool/img/2023/09/power-automate-http-post.png)

**Parse JSON**

Parse the response body as JSON to extract the scanned image.

![power automate parse JSON](https://www.dynamsoft.com/codepool/img/2023/09/power-automate-parse-json-image.png)


The schema of the JSON response is as follows:

```json
{
    "type": "object",
    "properties": {
        "image": {
            "type": "string"
        }
    }
}
```

**Return value(s) to Power Pages**

Return the image name to the Power App page.

![power automate Return value(s) to Power Pages](https://www.dynamsoft.com/codepool/img/2023/09/power-automate-return-value.png)

### 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.

```js
ClearCollect( Devices, GetDevices.Run());
```

![Get device event](https://www.dynamsoft.com/codepool/img/2023/09/get-device-event.png)

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.

![power automate collection](https://www.dynamsoft.com/codepool/img/2023/09/power-app-collection.png)


**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.

![power automate dropdown display](https://www.dynamsoft.com/codepool/img/2023/09/power-automate-dropdown-display.png)

**Acquire a document image**

Click on the `Scan` button and then assign the following code to its `OnSelect` property.

```js
Set(jsonString, Concatenate("{", """scan""", ":", DeviceList.Selected.Device, "}"));
Set(data, ScanDocument.Run(jsonString));
```

![scan document event](https://www.dynamsoft.com/codepool/img/2023/09/scan-document-event.png)

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.

![variable data](https://www.dynamsoft.com/codepool/img/2023/09/variable-store.png)

**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.

![power automate image display](https://www.dynamsoft.com/codepool/img/2023/09/image-url.png)


### Step5: Test the App

![Scan document in Power App Canvas App](https://www.dynamsoft.com/codepool/img/2023/09/power-app-canvas-document-scan.gif)