Использование Excel VBA для передачи содержимого в OneNote - статьи TechTV

В августе Microsoft выпустила версию OneNote с пакетом обновления 1 (SP1). Это обязательное обновление. Они добавили множество невероятных функций, в том числе интерфейс прикладного программирования, который позволяет другим приложениям передавать данные в OneNote.

Microsoft предлагает несколько отличных веб-сайтов, которые научат вас использовать VB.Net для передачи данных в OneNote. Но поскольку это сайт, вы, я и другие 200 миллионов пользователей Office больше всего озабочены тем, как отправлять данные в OneNote с помощью Office VBA. Я счастлив сказать, что это МОЖНО сделать. Эта страница проведет вас через все, что вам нужно для этого.

Я предполагаю, что вы в меру знакомы с VBA. Если это не так, я настоятельно рекомендую VBA и макросы для Microsoft Excel, книгу, предназначенную для того, чтобы кто-то начал изучать VBA.

Обзор

Вы можете отправить данные в OneNote, отформатировав их как данные XML. XML - довольно новая концепция. Это что-то вроде HTML. Думайте об этом как о файле CSV на стероидах. Вы можете прочитать мое Введение в XML.

По сути, ваша программа VBA должна записать XML-файл, а затем передать его содержимое в OneNote с помощью метода .Import. XML-файл должен содержать следующие элементы:

  • Элемент EnsurePage для каждой страницы, на которую вы хотите писать. Если страница не существует, OneNote создаст ее за вас. Теоретически вы должны иметь контроль и размещать страницу после определенной существующей страницы. Однако на практике это не работает.
  • Элемент PlaceObject для каждого элемента, который вы хотите добавить на страницу. Вы указываете местоположение X и Y для элемента и источник элемента. Элементом может быть изображение, объект Ink или текст в формате HTML. Вы могли подумать, что, поскольку OneNote читает из HTML, вы можете передать таблицу с тегами TR и TD, но это не работает. Вы можете передавать текст только с тегами BR и P для добавления перевода строки. Теги UL и LI должны работать. Теги шрифтов действительно работают.

Попался

Чтобы обновить существующую страницу, вы должны знать глобальный уникальный идентификатор (GUID) для этой страницы. Похоже, что нет способа найти GUID для существующей страницы в OneNote. Это означает, что вы можете обновлять или удалять элементы на существующей странице только в том случае, если вы создали страницу программным способом и сохранили GUID, используемый для создания этой страницы в своей книге. В приведенном ниже примере используется нестандартное место на листе для сохранения идентификатора GUID для страницы, таблицы данных и диаграммы.

GUID

Каждой новой странице в OneNote нужен GUID. Каждому новому объекту, размещенному на странице, нужен GUID. Хотя сгенерировать идентификаторы GUID из VB.Net легко, найти способ сгенерировать идентификаторы GUID из VBA было трудно. Всем 200 миллионам пользователей Office VBA необходимо дать совет Майклу Каплану из Trigeminal Software. Майкл, кажется, единственный в мире человек, взломавший код создания GUID из VBA. Он любезно поделился этим кодом со всем миром. Ознакомьтесь с полным кодом на его сайте. С разрешения Майкла я скопировал сюда только функции, необходимые для создания нового GUID в VBA. Вставьте модуль в свой проект и включите в него следующий код.

'------------------------------------------ ' 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

Добавление ссылки

В VBA используйте Инструменты - Ссылки, чтобы добавить ссылку на библиотеку объектов OneNote 1.1. Это позволит вам объявить новый объект CSimpleImporter, а затем использовать для объекта методы .Import и .NavigateToPage.

Пример использования

Эта книга Excel содержит систему ежедневных отчетов. Для каждого магазина в местной сети есть один рабочий лист. Каждая страница содержит таблицу, показывающую ежедневные продажи, и диаграмму, показывающую прогресс в достижении ежемесячной цели.

Код VBA добавит новый раздел под названием DailySales. Для каждого магазина будет добавлена ​​одна новая страница. Диаграмма из рабочего листа экспортируется как файл GIF и импортируется в OneNote. Данные с листа добавляются в OneNote в виде столбца HTML.

Ежедневные продажи

Следующий код используется в 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.

Интересные статьи...