Showing posts with label EXCEL. Show all posts
Showing posts with label EXCEL. Show all posts

Thursday, June 8, 2017

[office.js] Create Excel add-in with Angular

 office.js    Office 2016    Excel online    Angular  


Introduction


The JavaScript API for Office enables you to create web applications that interact with the object models in Office host applications.


Notice that some functions on latest office.js are only supported by Office 365, Office 2016. I will use Excel online to run the custom add-in in this sample.



Environment


Excel online




Implement


Install packages



Include office.js types into tsconfig.app.json

tsconfig.app.json

"types": [
  "@types/office-js"
]



Enable polyfills for IE

polyfill.ts



Update maint.ts

maint.ts

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

declare const Office: any;

Office.initialize = function () {
    const platform = platformBrowserDynamic();
    platform.bootstrapModule(AppModule);
};





Start writing add-in

Open app.component.ts, we will write the logic codes inside, which will generate a table with row data.

import { Component, ApplicationRef } from '@angular/core';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})

export class AppComponent {

    title = 'Excel add-in demo';
    data = [];

    constructor(private appRef: ApplicationRef) { }

    private render() {

        Excel.run(function (ctx) {
            const worksheet: Excel.Worksheet =
              ctx.workbook.worksheets.getActiveWorksheet();

            //Clear
            worksheet.getRange().clear();

            return ctx.sync().then(function () {

                var myTable = new Office.TableData();
                myTable.headers = ["Name", "Title", "Duty"];
                myTable.rows = [["JB", "TPM", "Product & Project management"], ["Lily", " Assistant Manager", "Finance, banking"], ["Leia", "Kid", "Play, eat and sleep :P"]];


                //See also : https://dev.office.com/reference/add-ins/shared/document.setselecteddataasync
                Office.context.document.setSelectedDataAsync(myTable, {
                    coercionType: Office.CoercionType.Table
                },
                  function (asyncResult) {
                      if (asyncResult.status === Office.AsyncResultStatus.Failed) {
                          console.log("Error: " + asyncResult.error.message);
                      }
                  });
            });
        }).catch(function (error) {
            console.log("Error: " + error);
            if (error instanceof OfficeExtension.Error) {
                console.log("Debug info: " + JSON.stringify(error.debugInfo));
            }
        });

    }
}




So far we completed our excel add-in sample code.
But there are two MUST-DO before we can use it.

1. The web app add-in MUST be HTTPS.
2. Create Manifest.xml



Enable HTTPS on localhost

Install BrowserSync

npm install browser-sync --save -dev


Go to \node_modules\browser-sync\lib\server\certs, copy
server.crt
server.key

to \assets\certs or other folder you like.



Start Angular application with the following command to enable HTTPS.

ng serve --ssl --ssl-key \"assets\\certs\\server.key\" --ssl-cert \"assets\\certs\\server.crt\



You can put the command to package.json’s scripts.

"scripts": {
  "ng": "ng",
  "start": "ng serve",
  "startssl": "ng serve --ssl --ssl-key \"assets\\certs\\server.key\" --ssl-cert \"assets\\certs\\server.crt\"",
  "build": "ng build",
  "test": "ng test",
  "lint": "ng lint",
  "e2e": "ng e2e"
}



Then start it like this,

$> npm run startssl



Open https://localhost:4200 on IE, and install the certification.







Create Manifest.xml

What is Manifest.xml?
The XML manifest file of an Office Add-in describes how your add-in should be activated when an end user installs and uses it with Office documents and applications. (From dev.office.com)


How to create Manifest.xml?


$> npm install -g yo generator-office

After installing it, use the following command to run the generator.

$> yo office





Update Manifest.xml

1.  Replace localhost:3000 to localhost:4200
2.  Update the information, such as Description, ProviderName, …
3.  Notice that if you have send request to cross domain, add the domain names on AppDomains.




For Excel 2016

If you are using Excel 2016, set a share folder and copy the Manifest.xml into it.
Open the Excel, and add the share folder’s path into trusted application directory.

PS. Sorry, I don’t have Office 2016, so I use Excel 2013 for the screen printing. However, the steps are the same on Excel 2016.





And now you can use the add-in like following.







For Excel online








Demo




Debug



For Excel

Ø  Visual Studio is required

First close all IE.
In Visual Studio,  open Attach to process(Ctrl+Alt+P)  and select attach to “script”.




Choose the two iexplore.exe processes and attach them.





Now we can debug our add-in in Visual Studio.





For Excel online

Use the browser Dev tools.




Reference






Saturday, May 27, 2017

[Excel VBA] Generate QR Code (2)

 Excel   VBA    QR Code  


Introduction


延續上一篇[Excel VBA] Generate QR Code(1)的程式碼,我們在需要產生多個QR Code的需求中,便需要建立一個專用的資料夾來存放不同的QR Code圖片,以讓Excel在每個QR CodeReference link不至於參考到同一張圖片。

我們將學習以下VBA之應用:
1.  產生多個QR Code
2.  如何操作非工作(Activate)中之WorkSheet儲存格
3.  如何建立資料夾


Implement


目標

我們將以下每筆資料(共四筆)分別產出一張QR Code並放到另外一張工作表:QR Code
並且在儲存後下次重新打開,儲存的四張QR Code是正確的。







設定工作表及儲存格名稱

請先設定好兩張工作表(WorkSheet)的名稱,然後在QR Code工作表,設定以下儲存格名稱分別為
Agile1, Agile2 ~ Agile4






在產生QR Code按鈕的事件程式碼,以迴圈讀取每筆資料




Private Sub QRCodeGen_Click()
    Dim idx As Integer
    For idx = 1 To 4
        genQRcode(idx)
    Next idx
End Sub


主程式

Private Sub genQRcode(idx As Integer)
    Dim qrcodeValue As String
    qrcodeValue = ActiveSheet.Cells(idx, 1).value 'QR Code value

    ' Set image path
    Dim qrcodeImgDir As String ' QR Code圖片資料夾位置
    Dim qrcodeImgPath As String ' QR Code圖片位置
    qrcodeImgDir = ActiveWorkbook.Path & "\" & Format(DateTime.Now, "yyyy-MM-dd")
   
    ' Set different image name for every QR Code
    qrcodeImgPath = qrcodeImgDir & "\" & "qrcode" & "_" & idx & Format(DateTime.Now, "hhmmss") & ".png"

    ' Create image folder
    If Dir(qrcodeImgDir, vbDirectory) = "" Then
        createDirectory qrcodeImgDir
    End If

    'Create QR Code image
    Call getQRCodeImg(qrcodeImgPath, qrcodeValue)

    'Set QR Code image to  another WorkSheet
    Dim sheet As Worksheet
    Dim cellName As String
    Dim qrcodeRange As Range
      Set sheet = ActiveWorkbook.Sheets("QR Code") ' Get another WorkSheet
      cellName = "Agile" & idx
      Set qrcodeRange = sheet.Range(cellName)
      Call deleteCell(sheet, qrcodeRange)
    Call appendQRCode(sheet, qrcodeRange, qrcodeImgPath)

End Sub


建立存放QR Code圖片的資料夾

Sub createDirectory(directoryPath)
    MkDir directoryPath
End Sub



更新函式: 傳入放QR Code的工作表和儲存格

Private Sub appendQRCode(sheet As Worksheet, qrcodeRange As Range, qrcodeImgPath As String)

    Dim img As Picture
    Set img = sheet.Pictures.Insert(qrcodeImgPath)

    With img
        .ShapeRange.LockAspectRatio = msoFalse
        '.Top = ActiveSheet.Cells(33, 10).Top
        '.Left = ActiveSheet.Cells(33, 10).Left
        .Left = qrcodeRange.Left + 5
        .Top = qrcodeRange.Top + 5
    End With
End Sub

Private Sub deleteCell(sheet As Worksheet, curcell As Range)
    Dim sh As Shape
    For Each sh In sheet.Shapes
        If sh.TopLeftCell.Address = curcell.Address Then sh.Delete
    Next
End Sub




產生QR Code

此函式沒有變更,只列出來供參考。

Private Sub getQRCodeImg(imgPath As String, value As String)
    Dim fileNum As Long
    Dim apiUri As String
    Dim fileData() As Byte
    Dim tmpImgPath As String
    Dim winHttpReq As Object
    Set winHttpReq = CreateObject("WinHttp.WinHttpRequest.5.1")

    apiUri = "https://chart.googleapis.com/chart?cht=qr&chs=130x130&chl=" + value

    winHttpReq.Open "GET", apiUri, False
    winHttpReq.Send

    fileData = winHttpReq.ResponseBody

    Open imgPath For Binary Access Write As #1
    Put #1, 1, fileData
    Close #1
End Sub




Demo






Reference