Sử dụng Excel VBA để đẩy nội dung lên OneNote - TechTV Articles

Vào tháng 8, Microsoft đã phát hành phiên bản SP1 của OneNote. Đây là một nâng cấp phải có. Họ đã thêm nhiều tính năng đáng kinh ngạc, bao gồm một giao diện lập trình ứng dụng cho phép các ứng dụng khác đẩy dữ liệu lên OneNote.

Microsoft cung cấp một số trang web tuyệt vời sẽ dạy bạn cách sử dụng VB.Net để đẩy dữ liệu vào OneNote. Tuy nhiên, vì đây là trang web, bạn và tôi và 200 triệu người dùng Office khác quan tâm nhất đến cách đẩy dữ liệu lên OneNote bằng Office VBA. Tôi rất vui khi nói rằng điều này CÓ THỂ được thực hiện. Trang này sẽ hướng dẫn bạn tất cả những gì bạn cần để hoàn thành công việc.

Tôi sẽ cho rằng bạn vừa phải quen thuộc với VBA. Nếu bạn chưa, tôi thực sự khuyên bạn nên sử dụng VBA & Macros cho Microsoft Excel, cuốn sách được thiết kế để đưa ai đó lên đường học tập VBA.

Tổng quat

Bạn có thể gửi dữ liệu tới OneNote bằng cách định dạng dữ liệu dưới dạng dữ liệu XML. XML là một khái niệm khá mới. Nó giống như HTML. Hãy coi nó như một tệp CSV trên steroid. Bạn có thể đọc phần Giới thiệu về XML của tôi.

Về cơ bản, chương trình VBA của bạn cần ghi ra một tệp XML, sau đó chuyển nội dung của tệp XML đến OneNote bằng phương thức .Import. Tệp XML cần phải chứa các phần tử sau:

  • Một phần tử EnsurePage cho mỗi trang mà bạn muốn viết. Nếu trang không tồn tại, OneNote sẽ tạo trang cho bạn. Về lý thuyết, bạn phải có quyền kiểm soát và đặt trang sau một trang hiện có cụ thể. Tuy nhiên, trong thực tế, điều này dường như không hoạt động.
  • Phần tử PlaceObject cho mỗi mục mà bạn muốn thêm vào trang. Bạn chỉ định vị trí X & Y cho mặt hàng và nguồn của mặt hàng. Một mục có thể là hình ảnh, đối tượng Ink hoặc văn bản ở định dạng HTML. Bạn sẽ nghĩ rằng vì OneNote đọc từ HTML, bạn thực sự có thể chuyển một bảng có thẻ TR và TD, nhưng điều này không hoạt động. Bạn bị hạn chế chuyển văn bản có thẻ BR và P để thêm nguồn cấp dữ liệu. Các thẻ UL & LI dường như hoạt động. Thẻ phông chữ hoạt động.

Gotcha

Để cập nhật một trang hiện có, bạn phải biết Mã định danh duy nhất trên toàn cầu (GUID) cho trang đó. Dường như không có cách nào để tìm GUID cho một trang hiện có trong OneNote. Điều này có nghĩa là bạn chỉ có thể cập nhật hoặc xóa các mục trên trang hiện có nếu bạn đã tạo trang theo chương trình và đã lưu trữ GUID được sử dụng để tạo trang đó trong sổ làm việc của mình. Ví dụ dưới đây sử dụng một vị trí khác trên trang tính để lưu GUID cho trang, bảng dữ liệu và biểu đồ.

HƯỚNG DẪN

Mỗi trang mới trong OneNote đều cần một GUID. Mọi đối tượng mới được đặt trên một trang đều cần một GUID. Mặc dù việc tạo GUID từ VB.Net rất dễ dàng, nhưng việc tìm cách tạo GUID từ VBA lại rất khó nắm bắt. Tất cả 200 triệu người dùng Office VBA cần phải giới thiệu cho Michael Kaplan của Trigeminal Software. Michael dường như là người duy nhất trên thế giới phá vỡ mã về cách tạo GUID từ VBA. Anh ấy đã ân cần chia sẻ mã này với thế giới. Kiểm tra mã hoàn chỉnh tại trang web của anh ấy. Với sự cho phép của Michael, tôi chỉ sao chép các hàm cần thiết để tạo GUID mới trong VBA tại đây. Chèn một mô-đun vào dự án của bạn và đưa đoạn mã sau vào mô-đun đó.

'------------------------------------------ ' basGuid from http://www.trigeminal.com/code/guids.bas ' You may use this code in your applications, just make ' sure you keep the (c) notice and don't publish it anywhere ' as your own ' Copyright (c) 1999 Trigeminal Software, Inc. All Rights Reserved '------------------------------------------ Option Compare Binary ' Note that although Variants now have ' a VT_GUID type, this type is unsupported in VBA, ' so we must define our own here that will have the same ' binary layout as all GUIDs are expected by COM to ' have. Public Type GUID Data1 As Long Data2 As Integer Data3 As Integer Data4(7) As Byte End Type Public Declare Function StringFromGUID2 Lib "ole32.dll" _ (rclsid As GUID, ByVal lpsz As Long, ByVal cbMax As Long) As Long Public Declare Function CoCreateGuid Lib "ole32.dll" _ (rclsid As GUID) As Long '------------------------------------------------------------ ' StGuidGen ' ' Generates a new GUID, returning it in canonical ' (string) format '------------------------------------------------------------ Public Function StGuidGen() As String Dim rclsid As GUID If CoCreateGuid(rclsid) = 0 Then StGuidGen = StGuidFromGuid(rclsid) End If End Function '------------------------------------------------------------ ' StGuidFromGuid ' ' Converts a binary GUID to a canonical (string) GUID. '------------------------------------------------------------ Public Function StGuidFromGuid(rclsid As GUID) As String Dim rc As Long Dim stGuid As String ' 39 chars for the GUID plus room for the Null char stGuid = String$(40, vbNullChar) rc = StringFromGUID2(rclsid, StrPtr(stGuid), Len(stGuid) - 1) StGuidFromGuid = Left$(stGuid, rc - 1) End Function

Thêm tham chiếu

Trong VBA, sử dụng Công cụ - Tham chiếu để thêm tham chiếu vào Thư viện đối tượng OneNote 1.1. Điều này sẽ cho phép bạn khai báo một đối tượng CSimpleImporter mới và sau đó sử dụng các phương thức .Import và .NavigateToPage trên đối tượng.

Nghiên cứu điển hình

Sổ làm việc Excel này chứa hệ thống báo cáo hàng ngày. Có một bảng tính cho mỗi cửa hàng trong chuỗi cửa hàng địa phương. Mỗi trang chứa một bảng hiển thị doanh số hàng ngày và một biểu đồ hiển thị tiến trình hướng tới mục tiêu hàng tháng.

Mã VBA sẽ thêm một phần mới có tên là DailySales. Một trang mới sẽ được thêm vào cho mỗi cửa hàng. Biểu đồ từ trang tính được xuất dưới dạng tệp GIF và được nhập vào OneNote. Dữ liệu từ trang tính được thêm vào OneNote dưới dạng một cột HTML.

Doanh số hàng ngày

Đoạn mã sau được sử dụng trong Excel.

Sub CreateUpdateOneNoteReport() ' Requires basGuid module from above Dim Cht As Chart fname = "C:OneNoteImport.xml" On Error Resume Next Kill (fname) On Error GoTo 0 ' Do we need new GUID's? For Each ws In ThisWorkbook.Worksheets If Not ws.Range("J22").Value> "" Then ws.Range("J22").Value = StGuidGen() End If If Not ws.Range("J23").Value> "" Then ws.Range("J23").Value = StGuidGen() End If If Not ws.Range("J24").Value> "" Then ws.Range("J24").Value = StGuidGen() End If Next ws ' Build a temporary XML file fname = "C:OneNoteImport.xml" On Error Resume Next Kill (fname) On Error GoTo 0 Open fname For Output As #1 Print #1, " " Print #1, " " ' Make sure that for each page, we have a page FirstPage = True DateStr = Format(Date - 1, "yyyy-mm-dd") & "T21:00:00-06:00" For Each ws In ThisWorkbook.Worksheets ThisTitle = ws.Name ThisGuid = ws.Range("J22").Value Print #1, " " FirstPage = False LastGuid = ThisGuid Next ws For Each ws In ThisWorkbook.Worksheets ThisTitle = ws.Name ThisImage = "C: " & ThisTitle & ".gif" ThisGuid = ws.Range("J22").Value ChartGuid = ws.Range("J24").Value TableGuid = ws.Range("J23").Value ' Export the Chart Set Cht = ws.ChartObjects(1).Chart Cht.Export Filename:=ThisImage, FilterName:="GIF" ' Place the Chart on the top, right side Print #1, "" Print #1, " " Print #1, "" Print #1, " " Print #1, " " Print #1, "  
Resulting OneNote Notebook

Apparent Bugs

In the book, I mentioned an apparent bug with "insertafter". I forgot that XML is case sensitive. If you use "insertAfter", then everything works fine. Thanks to Donovan Lange at Microsoft for pointing this out.

I am guessing that the next issue is not a bug - the code is probably working like Microsoft intended, but they missed an opportunity to do something the right way. You are allowed to specify a date and time in the EnsurePage section of the XML. This date and time is only used if the page does not exist. Given that Microsoft later allows us to update the page by remembering the GUID, they really should have allowed us to update the date and time on the page. In the example here, we are pushing new data each day, yet the date is always going to show that it is as of the first time that the program was run. This is disappointing.

thú vị bài viết...