Manifest for Office Add-In not pulling for some reason, stiil debugging.
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
# dependencies (bun install)
|
||||
node_modules
|
||||
|
||||
# output
|
||||
out
|
||||
dist
|
||||
*.tgz
|
||||
|
||||
# code coverage
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# logs
|
||||
logs
|
||||
_.log
|
||||
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# caches
|
||||
.eslintcache
|
||||
.cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# IntelliJ based IDEs
|
||||
.idea
|
||||
|
||||
# Finder (MacOS) folder config
|
||||
.DS_Store
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"plugins": [
|
||||
"office-addins"
|
||||
],
|
||||
"extends": [
|
||||
"plugin:office-addins/recommended"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
|
||||
// List of extensions which should be recommended for users of this workspace.
|
||||
"recommendations": [
|
||||
"ms-edgedevtools.vscode-edge-devtools",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode",
|
||||
"msoffice.microsoft-office-add-in-debugger"
|
||||
],
|
||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||
"unwantedRecommendations": []
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Excel Desktop (Edge Chromium)",
|
||||
"type": "msedge",
|
||||
"request": "attach",
|
||||
"port": 9229,
|
||||
"timeout": 600000,
|
||||
"webRoot": "${workspaceRoot}",
|
||||
"preLaunchTask": "Debug: Excel Desktop",
|
||||
"postDebugTask": "Stop Debug"
|
||||
},
|
||||
{
|
||||
"name": "Excel Desktop (Edge Legacy)",
|
||||
"type": "office-addin",
|
||||
"request": "attach",
|
||||
"url": "https://localhost:3000/taskpane.html?_host_Info=Excel$Win32$16.01$en-US$$$$0",
|
||||
"port": 9222,
|
||||
"timeout": 600000,
|
||||
"webRoot": "${workspaceRoot}",
|
||||
"preLaunchTask": "Debug: Excel Desktop",
|
||||
"postDebugTask": "Stop Debug"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"typescript"
|
||||
]
|
||||
}
|
||||
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Build (Development)",
|
||||
"type": "npm",
|
||||
"script": "build:dev",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"presentation": {
|
||||
"clear": true,
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Build (Production)",
|
||||
"type": "npm",
|
||||
"script": "build",
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"clear": true,
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Debug: Excel Desktop",
|
||||
"type": "shell",
|
||||
"command": "npm",
|
||||
"args": [
|
||||
"run",
|
||||
"start",
|
||||
"--",
|
||||
"desktop",
|
||||
"--app",
|
||||
"excel"
|
||||
],
|
||||
"presentation": {
|
||||
"clear": true,
|
||||
"panel": "dedicated"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Debug: Outlook Desktop",
|
||||
"type": "shell",
|
||||
"command": "npm",
|
||||
"args": [
|
||||
"run",
|
||||
"start",
|
||||
"--",
|
||||
"desktop",
|
||||
"--app",
|
||||
"outlook"
|
||||
],
|
||||
"presentation": {
|
||||
"clear": true,
|
||||
"panel": "dedicated"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Debug: PowerPoint Desktop",
|
||||
"type": "shell",
|
||||
"command": "npm",
|
||||
"args": [
|
||||
"run",
|
||||
"start",
|
||||
"--",
|
||||
"desktop",
|
||||
"--app",
|
||||
"powerpoint"
|
||||
],
|
||||
"presentation": {
|
||||
"clear": true,
|
||||
"panel": "dedicated"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Debug: Word Desktop",
|
||||
"type": "shell",
|
||||
"command": "npm",
|
||||
"args": [
|
||||
"run",
|
||||
"start",
|
||||
"--",
|
||||
"desktop",
|
||||
"--app",
|
||||
"word"
|
||||
],
|
||||
"presentation": {
|
||||
"clear": true,
|
||||
"panel": "dedicated"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Dev Server",
|
||||
"type": "npm",
|
||||
"script": "dev-server",
|
||||
"presentation": {
|
||||
"clear": true,
|
||||
"panel": "dedicated"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Install",
|
||||
"type": "npm",
|
||||
"script": "install",
|
||||
"presentation": {
|
||||
"clear": true,
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Lint: Check for problems",
|
||||
"type": "npm",
|
||||
"script": "lint",
|
||||
"problemMatcher": [
|
||||
"$eslint-stylish"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Lint: Fix all auto-fixable problems",
|
||||
"type": "npm",
|
||||
"script": "lint:fix",
|
||||
"problemMatcher": [
|
||||
"$eslint-stylish"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Stop Debug",
|
||||
"type": "npm",
|
||||
"script": "stop",
|
||||
"presentation": {
|
||||
"clear": true,
|
||||
"panel": "shared",
|
||||
"showReuseMessage": false
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Watch",
|
||||
"type": "npm",
|
||||
"script": "watch",
|
||||
"presentation": {
|
||||
"clear": true,
|
||||
"panel": "dedicated"
|
||||
},
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"targets": {
|
||||
"esmodules": false
|
||||
}
|
||||
}
|
||||
],
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0" xmlns:ov="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="TaskPaneApp">
|
||||
<Id>0b7d2846-9305-4e4b-906d-d73a6a4d286a</Id>
|
||||
<Version>1.0.0.0</Version>
|
||||
<ProviderName>Contoso</ProviderName>
|
||||
<DefaultLocale>en-US</DefaultLocale>
|
||||
<DisplayName DefaultValue="Create Job Folder"/>
|
||||
<Description DefaultValue="A template to get started."/>
|
||||
<IconUrl DefaultValue="https://localhost:3000/assets/icon-32.png"/>
|
||||
<HighResolutionIconUrl DefaultValue="https://localhost:3000/assets/icon-64.png"/>
|
||||
<SupportUrl DefaultValue="https://www.contoso.com/help"/>
|
||||
<AppDomains>
|
||||
<AppDomain>https://www.contoso.com</AppDomain>
|
||||
</AppDomains>
|
||||
<Hosts>
|
||||
<Host Name="Workbook"/>
|
||||
</Hosts>
|
||||
<DefaultSettings>
|
||||
<SourceLocation DefaultValue="https://localhost:3000/taskpane.html"/>
|
||||
</DefaultSettings>
|
||||
<Permissions>ReadWriteDocument</Permissions>
|
||||
<VersionOverrides xmlns="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="VersionOverridesV1_0">
|
||||
<Hosts>
|
||||
<Host xsi:type="Workbook">
|
||||
<DesktopFormFactor>
|
||||
<GetStarted>
|
||||
<Title resid="GetStarted.Title"/>
|
||||
<Description resid="GetStarted.Description"/>
|
||||
<LearnMoreUrl resid="GetStarted.LearnMoreUrl"/>
|
||||
</GetStarted>
|
||||
<FunctionFile resid="Commands.Url"/>
|
||||
<ExtensionPoint xsi:type="PrimaryCommandSurface">
|
||||
<OfficeTab id="TabHome">
|
||||
<Group id="CommandsGroup">
|
||||
<Label resid="CommandsGroup.Label"/>
|
||||
<Icon>
|
||||
<bt:Image size="16" resid="Icon.16x16"/>
|
||||
<bt:Image size="32" resid="Icon.32x32"/>
|
||||
<bt:Image size="80" resid="Icon.80x80"/>
|
||||
</Icon>
|
||||
<Control xsi:type="Button" id="TaskpaneButton">
|
||||
<Label resid="TaskpaneButton.Label"/>
|
||||
<Supertip>
|
||||
<Title resid="TaskpaneButton.Label"/>
|
||||
<Description resid="TaskpaneButton.Tooltip"/>
|
||||
</Supertip>
|
||||
<Icon>
|
||||
<bt:Image size="16" resid="Icon.16x16"/>
|
||||
<bt:Image size="32" resid="Icon.32x32"/>
|
||||
<bt:Image size="80" resid="Icon.80x80"/>
|
||||
</Icon>
|
||||
<Action xsi:type="ShowTaskpane">
|
||||
<TaskpaneId>ButtonId1</TaskpaneId>
|
||||
<SourceLocation resid="Taskpane.Url"/>
|
||||
</Action>
|
||||
</Control>
|
||||
</Group>
|
||||
</OfficeTab>
|
||||
</ExtensionPoint>
|
||||
</DesktopFormFactor>
|
||||
</Host>
|
||||
</Hosts>
|
||||
<Resources>
|
||||
<bt:Images>
|
||||
<bt:Image id="Icon.16x16" DefaultValue="https://localhost:3000/assets/icon-16.png"/>
|
||||
<bt:Image id="Icon.32x32" DefaultValue="https://localhost:3000/assets/icon-32.png"/>
|
||||
<bt:Image id="Icon.80x80" DefaultValue="https://localhost:3000/assets/icon-80.png"/>
|
||||
</bt:Images>
|
||||
<bt:Urls>
|
||||
<bt:Url id="GetStarted.LearnMoreUrl" DefaultValue="https://go.microsoft.com/fwlink/?LinkId=276812"/>
|
||||
<bt:Url id="Commands.Url" DefaultValue="https://localhost:3000/commands.html"/>
|
||||
<bt:Url id="Taskpane.Url" DefaultValue="https://localhost:3000/taskpane.html"/>
|
||||
</bt:Urls>
|
||||
<bt:ShortStrings>
|
||||
<bt:String id="GetStarted.Title" DefaultValue="Get started with your sample add-in!"/>
|
||||
<bt:String id="CommandsGroup.Label" DefaultValue="Commands Group"/>
|
||||
<bt:String id="TaskpaneButton.Label" DefaultValue="Show Task Pane"/>
|
||||
</bt:ShortStrings>
|
||||
<bt:LongStrings>
|
||||
<bt:String id="GetStarted.Description" DefaultValue="Your sample add-in loaded successfully. Go to the HOME tab and click the 'Show Task Pane' button to get started."/>
|
||||
<bt:String id="TaskpaneButton.Tooltip" DefaultValue="Click to Show a Taskpane"/>
|
||||
</bt:LongStrings>
|
||||
</Resources>
|
||||
<Requirements>
|
||||
<Sets DefaultMinVersion="1.1">
|
||||
<Set Name="IdentityAPI" MinVersion="1.3"/>
|
||||
</Sets>
|
||||
</Requirements>
|
||||
<WebApplicationInfo>
|
||||
<!-- Application (client) ID from your Azure AD / Entra app registration -->
|
||||
<Id>3c846e71-9609-40e1-b458-0eb805e21b9f</Id>
|
||||
<!-- The resource/audience URI your app uses; common pattern is api://{clientId} -->
|
||||
<Resource>api://3c846e71-9609-40e1-b458-0eb805e21b9f</Resource>
|
||||
<!-- Scopes your backend will request via OBO to call Microsoft Graph -->
|
||||
<Scopes>
|
||||
<Scope>User.Read</Scope>
|
||||
<Scope>Files.ReadWrite.All</Scope>
|
||||
<Scope>Sites.ReadWrite.All</Scope>
|
||||
<!-- Add any other Graph scopes you need -->
|
||||
</Scopes>
|
||||
</WebApplicationInfo>
|
||||
</VersionOverrides>
|
||||
</OfficeApp>
|
||||
+15493
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "office-addin-taskpane-js",
|
||||
"version": "0.0.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/OfficeDev/Office-Addin-TaskPane-JS.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"config": {
|
||||
"app_to_debug": "excel",
|
||||
"app_type_to_debug": "desktop",
|
||||
"dev_server_port": 3000
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack --mode production",
|
||||
"build:dev": "webpack --mode development",
|
||||
"dev-server": "webpack serve --mode development",
|
||||
"lint": "office-addin-lint check",
|
||||
"lint:fix": "office-addin-lint fix",
|
||||
"prettier": "office-addin-lint prettier",
|
||||
"signin": "office-addin-dev-settings m365-account login",
|
||||
"signout": "office-addin-dev-settings m365-account logout",
|
||||
"start": "office-addin-debugging start manifest.xml",
|
||||
"stop": "office-addin-debugging stop manifest.xml",
|
||||
"validate": "office-addin-manifest validate manifest.xml",
|
||||
"watch": "webpack --mode development --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.36.0",
|
||||
"regenerator-runtime": "^0.14.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.24.0",
|
||||
"@babel/preset-env": "^7.25.4",
|
||||
"@types/office-js": "^1.0.377",
|
||||
"@types/office-runtime": "^1.0.35",
|
||||
"acorn": "^8.11.3",
|
||||
"babel-loader": "^9.1.3",
|
||||
"copy-webpack-plugin": "^12.0.2",
|
||||
"eslint-plugin-office-addins": "^4.0.3",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-loader": "^5.0.0",
|
||||
"html-webpack-plugin": "^5.6.0",
|
||||
"office-addin-cli": "^2.0.3",
|
||||
"office-addin-debugging": "^6.0.3",
|
||||
"office-addin-dev-certs": "^2.0.3",
|
||||
"office-addin-lint": "^3.0.3",
|
||||
"office-addin-manifest": "^2.0.3",
|
||||
"office-addin-prettier-config": "^2.0.1",
|
||||
"os-browserify": "^0.3.0",
|
||||
"process": "^0.11.10",
|
||||
"source-map-loader": "^5.0.0",
|
||||
"webpack": "^5.95.0",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-dev-server": "5.1.0"
|
||||
},
|
||||
"prettier": "office-addin-prettier-config",
|
||||
"browserslist": [
|
||||
"last 2 versions",
|
||||
"ie 11"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. -->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||
|
||||
<!-- Office JavaScript API -->
|
||||
<script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
* See LICENSE in the project root for license information.
|
||||
*/
|
||||
|
||||
/* global Office */
|
||||
|
||||
Office.onReady(() => {
|
||||
// If needed, Office.js is ready to be called.
|
||||
});
|
||||
|
||||
/**
|
||||
* Shows a notification when the add-in command is executed.
|
||||
* @param event {Office.AddinCommands.Event}
|
||||
*/
|
||||
function action(event) {
|
||||
const message = {
|
||||
type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage,
|
||||
message: "Performed action.",
|
||||
icon: "Icon.80x80",
|
||||
persistent: true,
|
||||
};
|
||||
|
||||
// Show a notification message.
|
||||
Office.context.mailbox.item.notificationMessages.replaceAsync(
|
||||
"ActionPerformanceNotification",
|
||||
message
|
||||
);
|
||||
|
||||
// Be sure to indicate when the add-in command function is complete.
|
||||
event.completed();
|
||||
}
|
||||
|
||||
// Register the function with Office.
|
||||
Office.actions.associate("action", action);
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
* See LICENSE in the project root for license information.
|
||||
*/
|
||||
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ms-welcome__header {
|
||||
padding: 20px;
|
||||
padding-bottom: 30px;
|
||||
padding-top: 100px;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-flex-direction: column;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ms-welcome__main {
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-flex-wrap: nowrap;
|
||||
flex-wrap: nowrap;
|
||||
-webkit-align-items: center;
|
||||
align-items: center;
|
||||
-webkit-flex: 1 0 0;
|
||||
flex: 1 0 0;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.ms-welcome__main > h2 {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ms-welcome__features {
|
||||
list-style-type: none;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.ms-welcome__features.ms-List .ms-ListItem {
|
||||
padding-bottom: 20px;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.ms-welcome__features.ms-List .ms-ListItem > .ms-Icon {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.ms-welcome__action.ms-Button--hero {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.ms-Button.ms-Button--hero .ms-Button-label {
|
||||
color: #0078d7;
|
||||
}
|
||||
|
||||
.ms-Button.ms-Button--hero:hover .ms-Button-label,
|
||||
.ms-Button.ms-Button--hero:focus .ms-Button-label{
|
||||
color: #005a9e;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
b {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
/* taskpane.css */
|
||||
.container {
|
||||
padding: 10px;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
width: 80%;
|
||||
padding: 8px;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
background-color: #0078d4;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 15px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.action-btn:hover {
|
||||
background-color: #005a9e;
|
||||
}
|
||||
|
||||
#statusMessage {
|
||||
margin-top: 10px;
|
||||
font-size: 12px;
|
||||
color: #333;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. -->
|
||||
<!-- This file shows how to design a first-run page that provides a welcome screen to the user about the features of the add-in. -->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Contoso Task Pane Add-in</title>
|
||||
|
||||
<!-- Office JavaScript API -->
|
||||
<script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script>
|
||||
|
||||
<!-- For more information on Fluent UI, visit https://developer.microsoft.com/fluentui#/. -->
|
||||
<link rel="stylesheet" href="https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/office-ui-fabric-core/11.1.0/css/fabric.min.css"/>
|
||||
|
||||
<!-- Template styles -->
|
||||
<link href="taskpane.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
|
||||
<body class="ms-font-m ms-welcome ms-Fabric">
|
||||
|
||||
<div class="container">
|
||||
<h3>Create Project Folder</h3>
|
||||
<input type="text" id="projectName" placeholder="Enter Job Number" />
|
||||
<button id="createFolderBtn" class="action-btn">Create Folder & Document</button>
|
||||
<p id="statusMessage"></p>
|
||||
</div>
|
||||
|
||||
<header class="ms-welcome__header ms-bgColor-neutralLighter">
|
||||
<img width="90" height="90" src="../../assets/logo-filled.png" alt="Contoso" title="Contoso" />
|
||||
<h1 class="ms-font-su">Welcome</h1>
|
||||
</header>
|
||||
<section id="sideload-msg" class="ms-welcome__main">
|
||||
<h2 class="ms-font-xl">Please <a target="_blank" href="https://learn.microsoft.com/office/dev/add-ins/testing/test-debug-office-add-ins#sideload-an-office-add-in-for-testing">sideload</a> your add-in to see app body.</h2>
|
||||
</section>
|
||||
<main id="app-body" class="ms-welcome__main" style="display: none;">
|
||||
<h2 class="ms-font-xl"> Discover what Office Add-ins can do for you today! </h2>
|
||||
<ul class="ms-List ms-welcome__features">
|
||||
<li class="ms-ListItem">
|
||||
<i class="ms-Icon ms-Icon--Ribbon ms-font-xl"></i>
|
||||
<span class="ms-font-m">Achieve more with Office integration</span>
|
||||
</li>
|
||||
<li class="ms-ListItem">
|
||||
<i class="ms-Icon ms-Icon--Unlock ms-font-xl"></i>
|
||||
<span class="ms-font-m">Unlock features and functionality</span>
|
||||
</li>
|
||||
<li class="ms-ListItem">
|
||||
<i class="ms-Icon ms-Icon--Design ms-font-xl"></i>
|
||||
<span class="ms-font-m">Create and visualize like a pro</span>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="ms-font-l">Modify the source files, then click <b>Run</b>.</p>
|
||||
<div role="button" id="run" class="ms-welcome__action ms-Button ms-Button--hero ms-font-xl">
|
||||
<span class="ms-Button-label">Run</span>
|
||||
</div>
|
||||
<p><label id="item-subject"></label></p>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
||||
* See LICENSE in the project root for license information.
|
||||
*/
|
||||
|
||||
/* global console, document, Excel, Office */
|
||||
|
||||
window.addEventListener('error', (evt) => {
|
||||
console.error('WindowError:', {
|
||||
message: evt.message,
|
||||
filename: evt.filename,
|
||||
lineno: evt.lineno,
|
||||
colno: evt.colno,
|
||||
error: evt.error, // often the real Error object
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener('unhandledrejection', (evt) => {
|
||||
console.error('UnhandledRejection:', {
|
||||
reason: evt.reason, // might be the original Error
|
||||
});
|
||||
});
|
||||
|
||||
Office.onReady((info) => {
|
||||
if (info.host === Office.HostType.Excel) {
|
||||
document.getElementById("sideload-msg").style.display = "none";
|
||||
document.getElementById("app-body").style.display = "flex";
|
||||
document.getElementById("run").onclick = run;
|
||||
OfficeRuntime.auth.getAccessToken().then(token => console.log(token));
|
||||
document.getElementById("createFolderBtn").onclick = handleCreatePDF;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
async function handleCreatePDF() {
|
||||
const projectInput = document.getElementById("projectName").value.trim();
|
||||
const statusEl = document.getElementById("statusMessage");
|
||||
|
||||
if (!projectInput) {
|
||||
statusEl.textContent = "Please enter a project number.";
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
statusEl.textContent = "Processing...";
|
||||
|
||||
// 1. Get Excel data
|
||||
const jobData = await getJobData(projectInput);
|
||||
if (!jobData) {
|
||||
statusEl.textContent = "Job not found.";
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = await getFormData();
|
||||
|
||||
// 2. Get access token for Graph
|
||||
const accessToken = await getAccessToken();
|
||||
|
||||
// 3. Hardcoded SharePoint IDs
|
||||
const driveId = "b!9YOqqr2xM0G2DFBwMEJYY4UzQgocFddEtpLYWuS9_AtkCKl2q8yjQJteQ7Ti4QSx";
|
||||
const parentItemId = "01SPNXLDW3Y56HAWK5CNAJ4YJLLSQCUCJ7";
|
||||
|
||||
// 4. Create folder structure
|
||||
const mainFolderName = `[ ${jobData.Job_Number} ] - ${jobData.Job_Name}`;
|
||||
const mainFolderId = await createSharePointFolder(accessToken, driveId, parentItemId, mainFolderName);
|
||||
const subFolderId = await createSharePointFolder(accessToken, driveId, mainFolderId, "Manager Info");
|
||||
|
||||
// 5. Generate Word document and export as PDF
|
||||
const pdfBlob = await generatePDF(jobData, formData);
|
||||
|
||||
// 6. Upload PDF to SharePoint
|
||||
await uploadFileToSharePoint(accessToken, driveId, subFolderId, `${mainFolderName}.pdf`, pdfBlob);
|
||||
|
||||
statusEl.textContent = "✅ PDF created and uploaded successfully!";
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
statusEl.textContent = "❌ Error: " + error.message;
|
||||
}
|
||||
}
|
||||
|
||||
// Get Job Data from "Job Sheet"
|
||||
async function getJobData(jobNumber) {
|
||||
return Excel.run(async (context) => {
|
||||
const sheet = context.workbook.worksheets.getItem("Job Sheet");
|
||||
const usedRange = sheet.getUsedRange();
|
||||
usedRange.load("values");
|
||||
await context.sync();
|
||||
|
||||
const headers = usedRange.values[0];
|
||||
const rows = usedRange.values.slice(1);
|
||||
|
||||
const idxJobNumber = headers.indexOf("Job_Number");
|
||||
const idxJobName = headers.indexOf("Job_Name");
|
||||
const idxJobAddress = headers.indexOf("Job_Address");
|
||||
const idxJobDivision = headers.indexOf("Job_Division");
|
||||
const idxClientCustomer = headers.indexOf("Client_Customer");
|
||||
const idxContactPerson = headers.indexOf("Contact_Person");
|
||||
const idxEmail = headers.indexOf("Email");
|
||||
|
||||
const match = rows.find(r => r[idxJobNumber] == jobNumber);
|
||||
if (!match) return null;
|
||||
|
||||
return {
|
||||
Job_Number: match[idxJobNumber],
|
||||
Job_Name: match[idxJobName],
|
||||
Job_Address: match[idxJobAddress],
|
||||
Job_Division: match[idxJobDivision],
|
||||
Client_Customer: match[idxClientCustomer],
|
||||
Contact_Person: match[idxContactPerson],
|
||||
Email: match[idxEmail]
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// Get FormDat range
|
||||
async function getFormData() {
|
||||
return Excel.run(async (context) => {
|
||||
const sheet = context.workbook.worksheets.getItem("FormDat");
|
||||
const range = sheet.getRange("A1:C12");
|
||||
range.load("values");
|
||||
await context.sync();
|
||||
return range.values;
|
||||
});
|
||||
}
|
||||
|
||||
// Generate PDF using Word API
|
||||
async function generatePDF(jobData, formData) {
|
||||
return Word.run(async (context) => {
|
||||
const body = context.document.body;
|
||||
body.clear();
|
||||
|
||||
body.insertParagraph("Project Information", Word.InsertLocation.start);
|
||||
body.insertParagraph(`Job Number: ${jobData.Job_Number}`, Word.InsertLocation.end);
|
||||
body.insertParagraph(`Job Name: ${jobData.Job_Name}`, Word.InsertLocation.end);
|
||||
body.insertParagraph(`Address: ${jobData.Job_Address}`, Word.InsertLocation.end);
|
||||
body.insertParagraph(`Division: ${jobData.Job_Division}`, Word.InsertLocation.end);
|
||||
body.insertParagraph(`Client: ${jobData.Client_Customer}`, Word.InsertLocation.end);
|
||||
body.insertParagraph(`Contact: ${jobData.Contact_Person}`, Word.InsertLocation.end);
|
||||
body.insertParagraph(`Email: ${jobData.Email}`, Word.InsertLocation.end);
|
||||
|
||||
body.insertParagraph("\nForm Data:", Word.InsertLocation.end);
|
||||
formData.forEach(row => {
|
||||
body.insertParagraph(row.join(" | "), Word.InsertLocation.end);
|
||||
});
|
||||
|
||||
await context.sync();
|
||||
|
||||
// Export as PDF
|
||||
return new Promise((resolve, reject) => {
|
||||
Office.context.document.getFileAsync(Office.FileType.Pdf, (result) => {
|
||||
if (result.status === Office.AsyncResultStatus.Succeeded) {
|
||||
const file = result.value;
|
||||
const sliceCount = file.sliceCount;
|
||||
const slices = [];
|
||||
let sliceIndex = 0;
|
||||
|
||||
const getSlice = () => {
|
||||
file.getSliceAsync(sliceIndex, (sliceResult) => {
|
||||
if (sliceResult.status === Office.AsyncResultStatus.Succeeded) {
|
||||
slices.push(sliceResult.value.data);
|
||||
sliceIndex++;
|
||||
if (sliceIndex < sliceCount) {
|
||||
getSlice();
|
||||
} else {
|
||||
file.closeAsync();
|
||||
const blob = new Blob(slices, { type: "application/pdf" });
|
||||
resolve(blob);
|
||||
}
|
||||
} else {
|
||||
reject(sliceResult.error);
|
||||
}
|
||||
});
|
||||
};
|
||||
getSlice();
|
||||
} else {
|
||||
reject(result.error);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Get Access Token for Graph
|
||||
async function getAccessToken() {
|
||||
return new Promise((resolve, reject) => {
|
||||
Office.context.auth.getAccessTokenAsync({ allowSignInPrompt: true }, (result) => {
|
||||
if (result.status === "succeeded") {
|
||||
resolve(result.value);
|
||||
} else {
|
||||
reject(new Error(result.error.message));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Create folder in SharePoint
|
||||
async function createSharePointFolder(token, driveId, parentId, folderName) {
|
||||
const endpoint = `https://graph.microsoft.com/v1.0/drives/${driveId}/items/${parentId}/children`;
|
||||
const response = await fetch(endpoint, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({ name: folderName, folder: {}, "@microsoft.graph.conflictBehavior": "rename" })
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
if (!data.id) throw new Error(`Failed to create folder: ${JSON.stringify(data)}`);
|
||||
return data.id;
|
||||
}
|
||||
|
||||
// Upload PDF
|
||||
async function uploadFileToSharePoint(token, driveId, folderId, fileName, pdfBlob) {
|
||||
const endpoint = `https://graph.microsoft.com/v1.0/drives/${driveId}/items/${folderId}:/${fileName}:/content`;
|
||||
const response = await fetch(endpoint, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`
|
||||
},
|
||||
body: pdfBlob
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`Upload failed: ${errorText}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export async function run() {
|
||||
|
||||
try {
|
||||
await Excel.run(async (context) => {
|
||||
/**
|
||||
* Insert your Excel code here
|
||||
*/
|
||||
const range = context.workbook.getSelectedRange();
|
||||
|
||||
// Read the range address
|
||||
range.load("address");
|
||||
|
||||
// Update the fill color
|
||||
range.format.fill.color = "yellow";
|
||||
|
||||
await context.sync();
|
||||
console.log(`The range address was ${range.address}.`);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
const devCerts = require("office-addin-dev-certs");
|
||||
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||
|
||||
const urlDev = "https://localhost:3000/";
|
||||
const urlProd = "https://www.contoso.com/"; // CHANGE THIS TO YOUR PRODUCTION DEPLOYMENT LOCATION
|
||||
|
||||
async function getHttpsOptions() {
|
||||
const httpsOptions = await devCerts.getHttpsServerOptions();
|
||||
return { ca: httpsOptions.ca, key: httpsOptions.key, cert: httpsOptions.cert };
|
||||
}
|
||||
|
||||
module.exports = async (env, options) => {
|
||||
const dev = options.mode === "development";
|
||||
const config = {
|
||||
devtool: "source-map",
|
||||
entry: {
|
||||
polyfill: ["core-js/stable", "regenerator-runtime/runtime"],
|
||||
taskpane: ["./src/taskpane/taskpane.js", "./src/taskpane/taskpane.html"],
|
||||
commands: "./src/commands/commands.js",
|
||||
},
|
||||
output: {
|
||||
clean: true,
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".html", ".js"],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: "babel-loader",
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
exclude: /node_modules/,
|
||||
use: "html-loader",
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpg|jpeg|gif|ico)$/,
|
||||
type: "asset/resource",
|
||||
generator: {
|
||||
filename: "assets/[name][ext][query]",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "taskpane.html",
|
||||
template: "./src/taskpane/taskpane.html",
|
||||
chunks: ["polyfill", "taskpane"],
|
||||
}),
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: "assets/*",
|
||||
to: "assets/[name][ext][query]",
|
||||
},
|
||||
{
|
||||
from: "manifest*.xml",
|
||||
to: "[name]" + "[ext]",
|
||||
transform(content) {
|
||||
if (dev) {
|
||||
return content;
|
||||
} else {
|
||||
return content.toString().replace(new RegExp(urlDev, "g"), urlProd);
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "commands.html",
|
||||
template: "./src/commands/commands.html",
|
||||
chunks: ["polyfill", "commands"],
|
||||
}),
|
||||
],
|
||||
devServer: {
|
||||
headers: {
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
},
|
||||
server: {
|
||||
type: "https",
|
||||
options: env.WEBPACK_BUILD || options.https !== undefined ? options.https : await getHttpsOptions(),
|
||||
},
|
||||
port: process.env.npm_package_config_dev_server_port || 3000,
|
||||
},
|
||||
};
|
||||
|
||||
return config;
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
# officeaddin
|
||||
|
||||
To install dependencies:
|
||||
|
||||
```bash
|
||||
bun install
|
||||
```
|
||||
|
||||
To run:
|
||||
|
||||
```bash
|
||||
bun run index.ts
|
||||
```
|
||||
|
||||
This project was created using `bun init` in bun v1.3.3. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "officeaddin",
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@types/bun": ["@types/bun@1.3.3", "", { "dependencies": { "bun-types": "1.3.3" } }, "sha512-ogrKbJ2X5N0kWLLFKeytG0eHDleBYtngtlbu9cyBKFtNL3cnpDZkNdQj8flVf6WTZUX5ulI9AY1oa7ljhSrp+g=="],
|
||||
|
||||
"@types/node": ["@types/node@24.10.1", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ=="],
|
||||
|
||||
"bun-types": ["bun-types@1.3.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-z3Xwlg7j2l9JY27x5Qn3Wlyos8YAp0kKRlrePAOjgjMGS5IG6E7Jnlx736vH9UVI4wUICwwhC9anYL++XeOgTQ=="],
|
||||
|
||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||
|
||||
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<!-- Office.js must be present so the commands surface initializes -->
|
||||
https://appsforoffice.microsoft.com/lib/1/hosted/office.js</script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
// Minimal init; no custom handlers needed for ShowTaskpane
|
||||
Office.onReady(() => {
|
||||
// Commands surface is ready. Nothing else required for ShowTaskpane.
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
console.log("Hello via Bun!");
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "officeaddin",
|
||||
"module": "index.ts",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
// Environment setup & latest features
|
||||
"lib": ["ESNext"],
|
||||
"target": "ESNext",
|
||||
"module": "Preserve",
|
||||
"moduleDetection": "force",
|
||||
"jsx": "react-jsx",
|
||||
"allowJs": true,
|
||||
|
||||
// Bundler mode
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"noEmit": true,
|
||||
|
||||
// Best practices
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noImplicitOverride": true,
|
||||
|
||||
// Some stricter flags (disabled by default)
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noPropertyAccessFromIndexSignature": false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user