{"id":2106,"date":"2024-08-01T10:30:00","date_gmt":"2024-08-01T00:30:00","guid":{"rendered":"https:\/\/digitalbbq.au\/?p=2106"},"modified":"2024-07-28T10:05:04","modified_gmt":"2024-07-28T00:05:04","slug":"giving-excel-an-ai-brain-with-office-scripts","status":"publish","type":"post","link":"https:\/\/digitalbbq.au\/index.php\/2024\/08\/01\/giving-excel-an-ai-brain-with-office-scripts\/","title":{"rendered":"Giving Excel an AI Brain with Office Scripts"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">As an Excel user, I&#8217;m always looking for ways to automate repetitive tasks and make my workflow more efficient. That&#8217;s where Office Scripts come in. The way office scripts are advertised out of the box is that they&#8217;re a feature in Excel that enables you to automate tasks by recording your actions and replay them whenever I want. you can create scripts using the Action Recorder, which is great for consistent actions. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"520\" height=\"87\" src=\"https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/07\/e263eb14-cb86-481a-bcbd-6a3cfeaed7b5.png\" alt=\"\" class=\"wp-image-2107\" srcset=\"https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/07\/e263eb14-cb86-481a-bcbd-6a3cfeaed7b5.png 520w, https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/07\/e263eb14-cb86-481a-bcbd-6a3cfeaed7b5-300x50.png 300w\" sizes=\"auto, (max-width: 520px) 100vw, 520px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">But what if you want something more? Office scripts can handle that too, as the underlying technology that drives your office scripts is Typescript, which you can use the Code Editor to build out more advanced scripts. In this post, we&#8217;ll take a closer look at how I used the Code Editor to build an Office Script that integrates with a local language model (LLM) using a REST API call.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Not Every Problem Can Be Solved with Excel.. Or Can They?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">I had a dataset with hundreds of rows that required me to make decisions based on multiple pieces of information. The problem was that these decisions couldn&#8217;t be made using Excel functions alone. While you can build out complex formulas to work with text, such as using the ISNUMBER(SEARCH(x)) function and other methods, they&#8217;re very basic and not suitable for my task.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I knew I needed a more advanced solution, one that could provide a level of intelligence to the process. That&#8217;s when I turned to language models (LLMs). As I discussed in my previous post <a href=\"https:\/\/digitalbbq.au\/index.php\/2024\/04\/26\/a-no-code-guide-to-local-large-language-models\/\" data-type=\"post\" data-id=\"1978\">about self-hosting open source langauge models<\/a>, LLMs are not to be confused with artificial general intelligence (AGI). Instead, they&#8217;re designed to predict the next word in a sequence based on their training data. This gives the impression that they&#8217;re &#8220;thinking&#8221; when they provide responses, especially when they get it spot on. However, as anyone who&#8217;s worked with LLMs knows, they can also produce &#8220;hallucinations&#8221; &#8211; responses that are incorrect or nonsensical.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"516\" height=\"443\" src=\"https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/07\/image-1.png\" alt=\"\" class=\"wp-image-2111\" srcset=\"https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/07\/image-1.png 516w, https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/07\/image-1-300x258.png 300w\" sizes=\"auto, (max-width: 516px) 100vw, 516px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">To benefit the power of LLMs in my Excel project, I needed to provide context and guidance to ensure accurate responses. I realized that by concatenating relevant information from other cells using basic Excel formulas, I could create a prompt that would help the LLM provide a more accurate answer. It was a simple yet effective approach: <em>&#8220;Can you tell me the best match for x, pick the answer from the list of y?&#8221;<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With this approach in mind, I set out to integrate the LLM into my Excel workflow using Office Scripts. The basic steps to my code is:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Self-host a language model using LM Studio (<a href=\"https:\/\/digitalbbq.au\/index.php\/2024\/04\/26\/a-no-code-guide-to-local-large-language-models\/\" data-type=\"post\" data-id=\"1978\">how do I do that?<\/a>)<\/li>\n\n\n\n<li>Get the current selected cell<\/li>\n\n\n\n<li>Send the text to the local language model as a prompt<\/li>\n\n\n\n<li>Return the result to the cell in the next column<\/li>\n<\/ul>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"TypeScript\" data-shcb-language-slug=\"typescript\"><span><code class=\"hljs language-typescript\"><span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">main<\/span>(<span class=\"hljs-params\">workbook: ExcelScript.Workbook<\/span>) <\/span>{\n    <span class=\"hljs-comment\">\/\/ Get the active cell and its value<\/span>\n    <span class=\"hljs-keyword\">const<\/span> activeCell = workbook.getActiveCell();\n    <span class=\"hljs-keyword\">const<\/span> prompt: <span class=\"hljs-built_in\">string<\/span> = activeCell.getValue() <span class=\"hljs-keyword\">as<\/span> <span class=\"hljs-built_in\">string<\/span>;\n\n    <span class=\"hljs-comment\">\/\/ Define the payload for the POST request<\/span>\n    <span class=\"hljs-keyword\">const<\/span> payload = {\n        messages: &#091;\n            { <span class=\"hljs-string\">\"role\"<\/span>: <span class=\"hljs-string\">\"system\"<\/span>, <span class=\"hljs-string\">\"content\"<\/span>: <span class=\"hljs-string\">\"You are a helpful coding assistant.\"<\/span> },\n            { <span class=\"hljs-string\">\"role\"<\/span>: <span class=\"hljs-string\">\"user\"<\/span>, <span class=\"hljs-string\">\"content\"<\/span>: prompt }\n        ],\n        temperature: <span class=\"hljs-number\">0.7<\/span>, <span class=\"hljs-comment\">\/\/ Adjust the temperature based on your requirement<\/span>\n        max_tokens: <span class=\"hljs-number\">150<\/span>, <span class=\"hljs-comment\">\/\/ Adjust the max_tokens based on your requirement<\/span>\n        stream: <span class=\"hljs-literal\">false<\/span>\n    };\n\n\n    <span class=\"hljs-keyword\">const<\/span> uri: <span class=\"hljs-built_in\">string<\/span> = <span class=\"hljs-string\">'http:\/\/localhost:1234\/v1\/chat\/completions'<\/span>; <span class=\"hljs-comment\">\/\/ LM Studio server URL<\/span>\n\n\n    <span class=\"hljs-keyword\">try<\/span> {\n        <span class=\"hljs-comment\">\/\/ Make a call to the local LLM using the payload<\/span>\n        <span class=\"hljs-keyword\">const<\/span> chatCompletionResponse: Response = <span class=\"hljs-keyword\">await<\/span> fetch(uri, {\n            method: <span class=\"hljs-string\">\"POST\"<\/span>,\n            headers: {\n                <span class=\"hljs-string\">\"Content-Type\"<\/span>: <span class=\"hljs-string\">\"application\/json\"<\/span>\n            },\n            body: <span class=\"hljs-built_in\">JSON<\/span>.stringify(payload)\n        });\n\n        <span class=\"hljs-keyword\">if<\/span> (!chatCompletionResponse.ok) {\n            <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Error<\/span>(<span class=\"hljs-string\">`Server error: <span class=\"hljs-subst\">${chatCompletionResponse.statusText}<\/span>`<\/span>);\n        }\n\n        <span class=\"hljs-comment\">\/\/ Define the expected response structure<\/span>\n        <span class=\"hljs-keyword\">interface<\/span> ChatCompletionResponse {\n            choices: { message: { content: <span class=\"hljs-built_in\">string<\/span> } }&#091;];\n        }\n\n        <span class=\"hljs-keyword\">const<\/span> chatCompletionData: ChatCompletionResponse = <span class=\"hljs-keyword\">await<\/span> chatCompletionResponse.json();\n\n        <span class=\"hljs-comment\">\/\/ Extract the response content<\/span>\n        <span class=\"hljs-keyword\">const<\/span> responseContent: <span class=\"hljs-built_in\">string<\/span> = chatCompletionData.choices&#091;<span class=\"hljs-number\">0<\/span>].message.content;\n\n        <span class=\"hljs-comment\">\/\/ Place the response in the adjacent cell<\/span>\n        <span class=\"hljs-keyword\">const<\/span> nextCell = activeCell.getOffsetRange(<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">1<\/span>);\n        nextCell.setValue(responseContent);\n    } <span class=\"hljs-keyword\">catch<\/span> (error: unknown) {\n        <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">\"Error making request:\"<\/span>, error);\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">TypeScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">typescript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Here is an example of how you might use this code.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In column A, I have a list of yellow things. In column B, I have something I want to ask about in row 2, then in row 6, I&#8217;ve built out my LLM prompt with the following Excel formula:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">=<span class=\"hljs-string\">\"From the following list: \"<\/span>&amp;ARRAYTOTEXT(A1:A25,<span class=\"hljs-number\">0<\/span>)&amp;<span class=\"hljs-string\">\". Which item best describes \"<\/span>&amp;B2<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">With a slight modification to the code above, I&#8217;m sending my answer to cell B8.<\/p>\n\n\n\n<!-- iframe plugin v.6.0 wordpress.org\/plugins\/iframe\/ -->\n<iframe src=\"https:\/\/aitable.ai\/share\/shry8lsogoV0ofcTFKqZo\" loading=\"lazy\" scrolling=\"no\" style=\"width: 100%; aspect-ratio: 16 \/ 10; border:0; border-radius: 4px; overflow:hidden;\" width=\"100%\" height=\"500\" class=\"iframe-class\" frameborder=\"0\"><\/iframe>\n\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As you can see, my question to the LLM becomes:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"has-small-font-size wp-block-paragraph\">From the following list: Sunflowers, Bananas, Lemons, Daffodils, Corn, Yellow peppers, Bumblebees, Rubber ducks, Pineapples, School buses, Marigolds, Canaries, Yellow jackets, Yellow tulips, Goldfinches, Cheese, Mustard, Yellow apples, Yellow squash, Yellow traffic lights, Yellow highlighters, Yellow post-it notes, Yellow balloons, Sweetcorn, Dandelions. Which item best describes a fruit often associated with pyjamas<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">And the response is:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"has-small-font-size wp-block-paragraph\">\u00a0The item that best fits the description of being &#8220;a fruit often associated with pyjamas&#8221; would likely be bananas due to their yellow color and common presence in comfort-oriented clothing like pajama sets, which are frequently adorned with whimsical designs including fruits. While there might not always be an explicit connection between the two items (bananas and pyjamas), it&#8217;s a playful association that fits within cultural references to bananas as part of bedroom furnishings or thematic decorations for children\u2019s nightwear.<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">The response is far longer than we&#8217;d like it to be, so how do we fix that? When working with LLM API calls, the easiest ways to adjust the responses are to adjust the temperature and the token limit and then review either your prompt or the system role.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Think of tokens as words, or parts of words, and the temperature as verbosity from a range of 0 &#8211; 1, with 1 being more verbose and 0 being more concise.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After changing the temperature to 0.2 and the token limit to 20 and with no changes to the prompt, the answer is far less useful but its certainly shorter:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"has-small-font-size wp-block-paragraph\">The term &#8220;fruit&#8221; is typically used to describe the edible part of plants that usually<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">The next steps are to adjust the system role, the prompt, or both, however sometimes, this can result in things getting even worse. For example, using<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">    <span class=\"hljs-keyword\">const<\/span> payload = {\n        <span class=\"hljs-attr\">messages<\/span>: &#091;\n            { <span class=\"hljs-string\">\"role\"<\/span>: <span class=\"hljs-string\">\"system\"<\/span>, <span class=\"hljs-string\">\"content\"<\/span>: <span class=\"hljs-string\">\"You are a helpful object classification assistant\"<\/span> },\n            { <span class=\"hljs-string\">\"role\"<\/span>: <span class=\"hljs-string\">\"user\"<\/span>, <span class=\"hljs-string\">\"content\"<\/span>: From the following list: Sunflowers, Bananas, Lemons, Daffodils, Corn, Yellow peppers, Bumblebees, Rubber ducks, Pineapples, School buses, Marigolds, Canaries, Yellow jackets, Yellow tulips, Goldfinches, Cheese, Mustard, Yellow apples, Yellow squash, Yellow traffic lights, Yellow highlighters, Yellow post-it notes, Yellow balloons, Sweetcorn, Dandelions. Which item best describes a fruit often associated <span class=\"hljs-keyword\">with<\/span> pyjamas? Respond <span class=\"hljs-keyword\">in<\/span> <span class=\"hljs-number\">3<\/span> words or less\n }\n        ],\n        <span class=\"hljs-attr\">temperature<\/span>: <span class=\"hljs-number\">0.2<\/span>,\n        <span class=\"hljs-attr\">max_tokens<\/span>: <span class=\"hljs-number\">20<\/span>, <span class=\"hljs-comment\">\/\/ Adjust the max_tokens based on your requirement<\/span>\n        <span class=\"hljs-attr\">stream<\/span>: <span class=\"hljs-literal\">false<\/span>\n    };<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">We end up with this:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"has-small-font-size wp-block-paragraph\">&#8220;Yellow peppers&#8221; (though not typically worn as clothing) are the closest match<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">While we&#8217;re certainly making the responses shorter, the core part of the response is completely wrong. When you&#8217;re stuck getting silly errors and non-sensical results, this is when you need to start thinking about the model you&#8217;re using.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For each of these examples, I&#8217;ve been using Microsoft&#8217;s open-source Phi 3 mini instruct model, which is usually quite good when dealing with larger datasets, but it looks like it&#8217;s not that great for object classification tasks. But that&#8217;s the thing about hosting local LLMs, you can pick and choose what works best for you within the constraints of your hardware. There are so many variations of open source LLMs out there that are suited to particular tasks, or where others have tuned them to perform specific uses. You can even take one as a base and fine-tune it based on your own datasets.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With no change other than changing to Meta&#8217;s Llama 3 Instruct model, running the script again, things are looking much better!<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"has-small-font-size wp-block-paragraph\">Bananas are best!<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">In this situation, Llama 3 is clearly much better at following the instructions provided, we asked it to respond in 3 words or less, and it did exactly that, and what&#8217;s more, it was correct. That just leaves us to make a minor amendment to our prompt, instead of asking the LLM to response &#8220;in 3 words or less&#8221;, we now ask it to &#8220;Respond with only the correct answer from the list&#8221; and finally we get the response we want:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"has-small-font-size wp-block-paragraph\">Bananas<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">To be clear, this isn&#8217;t an exercise in saying that Llama 3 is better than Phi 3, but moreso to demonstrate that there is more than just your prompt and context required to get the desired results. I personally use both Llama 3 and Phi 3 (and many others) quite often depending on the task at hand.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Can&#8217;t Self Host an LLM? No Worries!<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;re unable to self-host an LLM on your machine, you&#8217;ve not nothing to worry about. Many of the local and cloud hosted open source LLM tools API is the same as the OpenAI API, so it doesn&#8217;t matter if you&#8217;re using OpenAI, VLLM, LM Studio, Ollama or many others, this same code should work for you. The only difference being that you would need to change the URI used in the code, and for cloud hosted services, you would need to include an API key.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Office Scripts &#8211; Not Just for Excel<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">One of the coolest things about Office Scripts is that they&#8217;re not limited to a single Excel file. Once you&#8217;ve saved a script, it&#8217;s automatically loaded into Excel every time you open it, as long as you&#8217;re connected to your Office 365 account or OneDrive. This means you can access your scripts from any device, without having to recreate them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But that&#8217;s not all &#8211; Office Scripts can also be integrated with Power Automate, allowing you to build complex flows that call scripts from your library. For example, I&#8217;ve built a regex script that I can call from Power Automate, which fills a gap in Power Automates native functionality. This opens up a whole new world of possibilities for automating tasks and workflows.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As an Excel user, I&#8217;m always looking for ways to automate repetitive tasks and make my workflow more efficient. That&#8217;s where Office Scripts come in. The way office scripts are advertised out of the box is that they&#8217;re a feature in Excel that enables you to automate tasks by recording your actions and replay them whenever I want. you can&#8230;<\/p>\n","protected":false},"author":1,"featured_media":2109,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"Learn how to automate tasks in Excel with Office Scripts and local language models. Discover how to integrate AI into your workflow and boost productivity.","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_seo_schema_type":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"Have you ever wondered what fruit is commonly associated with pyjamas? Discover how I used Office Scripts and a local language model to find the answer! Read my latest blog post to learn more about automating tasks with AI in Excel. #ExcelAI #OfficeScript","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[1],"tags":[82,73],"class_list":["post-2106","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-digital","tag-ai","tag-process"],"jetpack_publicize_connections":[],"jetpack-related-posts":[{"id":2686,"url":"https:\/\/digitalbbq.au\/index.php\/2026\/07\/16\/data-on-the-host-data-in-the-ifc-not-so-fast\/","url_meta":{"origin":2106,"position":0},"title":"Data on the Host, Data in the IFC? Not So Fast.","author":"Ryan Lenihan","date":"16 July 2026","format":false,"excerpt":"A few days after the last post, I got handed a model that seemed like it should have worked perfectly. The nested families were already set up as Shared. The IFC export was running. The geometry was coming through. But the asset data? Completely missing. When this happens, it\u2019s easy\u2026","rel":"","context":"In &quot;How to guides&quot;","block_context":{"text":"How to guides","link":"https:\/\/digitalbbq.au\/index.php\/category\/how-to-guides\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/07\/colorful-wooden-toy-blocks-on-wood-floor-2026-01-07-06-18-37-utc.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/07\/colorful-wooden-toy-blocks-on-wood-floor-2026-01-07-06-18-37-utc.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/07\/colorful-wooden-toy-blocks-on-wood-floor-2026-01-07-06-18-37-utc.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/07\/colorful-wooden-toy-blocks-on-wood-floor-2026-01-07-06-18-37-utc.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/07\/colorful-wooden-toy-blocks-on-wood-floor-2026-01-07-06-18-37-utc.jpg?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/07\/colorful-wooden-toy-blocks-on-wood-floor-2026-01-07-06-18-37-utc.jpg?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":2318,"url":"https:\/\/digitalbbq.au\/index.php\/2025\/01\/30\/data-security-backups-heres-what-to-include-in-your-bep\/","url_meta":{"origin":2106,"position":1},"title":"Data Security &amp; Backups. Here\u2019s What to Include in Your BEP","author":"Ryan Lenihan","date":"30 January 2025","format":false,"excerpt":"When working in a Common Data Environment (CDE) hosted in the cloud, it\u2019s easy to assume that data is automatically backed up. After all, the vendor running the platform has redundancies in place, right? The reality: While cloud-based CDE providers may have their own backup processes, these are not intended\u2026","rel":"","context":"In &quot;Digital&quot;","block_context":{"text":"Digital","link":"https:\/\/digitalbbq.au\/index.php\/category\/digital\/"},"img":{"alt_text":"Single cloud on a light blue background.","src":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/01\/single-cloud-on-a-light-blue-background-.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/01\/single-cloud-on-a-light-blue-background-.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/01\/single-cloud-on-a-light-blue-background-.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/01\/single-cloud-on-a-light-blue-background-.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/01\/single-cloud-on-a-light-blue-background-.jpg?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":2651,"url":"https:\/\/digitalbbq.au\/index.php\/2026\/05\/14\/revit-cloud-upgrades-part-5-making-acc-revit-upgrade-reports-usable\/","url_meta":{"origin":2106,"position":2},"title":"Revit Cloud Upgrades Part 5 \u2013\u00a0Making ACC Revit Upgrade Reports Usable","author":"Ryan Lenihan","date":"14 May 2026","format":false,"excerpt":"If you've been following along with the Revit Cloud Upgrade series, you should now be comfortable with reading the Test Upgrade Report properly, not just scanning it, but understanding what actually blocks an upgrade and what doesn't. That's great if the project is small and only has a few models,\u2026","rel":"","context":"In &quot;Digital&quot;","block_context":{"text":"Digital","link":"https:\/\/digitalbbq.au\/index.php\/category\/digital\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/05\/laptop-displaying-charts-and-graphs-on-an-office_sm.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/05\/laptop-displaying-charts-and-graphs-on-an-office_sm.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/05\/laptop-displaying-charts-and-graphs-on-an-office_sm.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/05\/laptop-displaying-charts-and-graphs-on-an-office_sm.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2026\/05\/laptop-displaying-charts-and-graphs-on-an-office_sm.jpg?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":1779,"url":"https:\/\/digitalbbq.au\/index.php\/2024\/02\/01\/better-file-and-folder-management-with-excel\/","url_meta":{"origin":2106,"position":3},"title":"Better File and Folder Management &#8211; With Excel","author":"Ryan Lenihan","date":"1 February 2024","format":false,"excerpt":"An old colleague shared this fantastic Excel file with me when I needed to bulk rename files. Our IT policies didn't allow us to install useful tools such as Better File Rename. The Excel file contains VBA macros that list folder contents and rename files, and it has now become\u2026","rel":"","context":"In &quot;Digital&quot;","block_context":{"text":"Digital","link":"https:\/\/digitalbbq.au\/index.php\/category\/digital\/"},"img":{"alt_text":"Files selection and management","src":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2024\/01\/files-selection-and-management.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2024\/01\/files-selection-and-management.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2024\/01\/files-selection-and-management.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2024\/01\/files-selection-and-management.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2024\/01\/files-selection-and-management.jpg?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2024\/01\/files-selection-and-management.jpg?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":2218,"url":"https:\/\/digitalbbq.au\/index.php\/2024\/10\/24\/email-productivity-with-ai-and-robotic-process-automation\/","url_meta":{"origin":2106,"position":4},"title":"Email Productivity with AI and Robotic Process Automation","author":"Ryan Lenihan","date":"24 October 2024","format":false,"excerpt":"If you're like me, some days you might receive a hundred or more emails on any given day, and managing that influx of emails can be tedious. Between coordinating with clients, handling project updates, and scheduling site visits, email can quickly become overwhelming. That\u2019s where email automation using LLMs like\u2026","rel":"","context":"In &quot;Digital&quot;","block_context":{"text":"Digital","link":"https:\/\/digitalbbq.au\/index.php\/category\/digital\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2024\/09\/b7004048-a68a-443b-a18d-64d7b4669509.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2024\/09\/b7004048-a68a-443b-a18d-64d7b4669509.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2024\/09\/b7004048-a68a-443b-a18d-64d7b4669509.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2024\/09\/b7004048-a68a-443b-a18d-64d7b4669509.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2024\/09\/b7004048-a68a-443b-a18d-64d7b4669509.jpg?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":2327,"url":"https:\/\/digitalbbq.au\/index.php\/2025\/02\/27\/the-button-why-some-demand-it-and-others-fear-it\/","url_meta":{"origin":2106,"position":5},"title":"The Button \u2013 Why Some Demand It, and Others Fear It","author":"Ryan Lenihan","date":"27 February 2025","format":false,"excerpt":"A while ago, my wife wrote a blog post about The Button\u2014specifically, the electric push-button and how it transformed the way we interact with machines. Before the push-button, people had to manually operate machines using cranks, levers, and mechanisms. When buttons were introduced, they revolutionized convenience\u2014but not without resistance. Some\u2026","rel":"","context":"In &quot;Digital&quot;","block_context":{"text":"Digital","link":"https:\/\/digitalbbq.au\/index.php\/category\/digital\/"},"img":{"alt_text":"The ominous red button","src":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/01\/the-ominous-red-button.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/01\/the-ominous-red-button.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/01\/the-ominous-red-button.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/01\/the-ominous-red-button.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/01\/the-ominous-red-button.jpg?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/digitalbbq.au\/wp-content\/uploads\/2025\/01\/the-ominous-red-button.jpg?resize=1400%2C800&ssl=1 4x"},"classes":[]}],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/digitalbbq.au\/wp-content\/uploads\/2024\/07\/spreadsheet-table-paper-with-pencil-with-math-number-education-concept-.jpg","_links":{"self":[{"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/posts\/2106","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/comments?post=2106"}],"version-history":[{"count":9,"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/posts\/2106\/revisions"}],"predecessor-version":[{"id":2118,"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/posts\/2106\/revisions\/2118"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/media\/2109"}],"wp:attachment":[{"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/media?parent=2106"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/categories?post=2106"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/digitalbbq.au\/index.php\/wp-json\/wp\/v2\/tags?post=2106"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}