Last active
May 25, 2022 23:15
-
-
Save mafrenet/e6e1eb26d3ff778edad73a4230b44b5b to your computer and use it in GitHub Desktop.
Create and retrieve rich data tool - building, retrieving and modifying rich data using valuesAsJson. This tool was created as a one-off example demonstrating the capabilities of the valuesAsJson API and it is not supported or maintained by Microsoft
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Create and retrieve rich data tool | |
description: >- | |
Create and retrieve rich data tool - building, retrieving and modifying rich | |
data using valuesAsJson. This tool was created as a one-off example | |
demonstrating the capabilities of the valuesAsJson API and it is not supported | |
or maintained by Microsoft | |
host: EXCEL | |
api_set: {} | |
script: | |
content: > | |
/** Copyright (c) Microsoft Corporation. Licensed under the MIT License. */ | |
const defaultType: string = "String"; | |
function textInputWithLabel(inputID: string, labelText: string, altText: | |
string): JQuery<HTMLElement>[] { | |
return [ | |
$("<td>").append($("<label/>", { for: inputID, class: "labels" }).text(labelText)), | |
$("<td>").append($("<input/>", { class: "inputBox " + inputID, type: "text", id: inputID, alt: altText })) | |
]; | |
} | |
function checkboxWithLabel(inputID: string, labelText: string, altText: | |
string): JQuery<HTMLElement> { | |
return $("<div/>", { class: "checkboxes" }) | |
.append($("<input/>", { type: "checkbox", class: inputID, checked: true, alt: altText })) | |
.append($("<label/>").text(labelText)); | |
} | |
function stringContent(): JQuery<HTMLElement> { | |
return basicContent("String"); | |
} | |
function booleanContent(): JQuery<HTMLElement> { | |
return basicContent("Boolean"); | |
} | |
function doubleContent(): JQuery<HTMLElement> { | |
return basicContent("Double"); | |
} | |
function basicContent(contentType: string): JQuery<HTMLElement> { | |
return $("<tr/>", { id: contentType, class: "fieldValueContents" }).append( | |
textInputWithLabel("basicValue", "Value: ", "value input box") | |
); | |
} | |
function webImageContent(): JQuery<HTMLElement>[] { | |
return [ | |
$("<tr/>", { id: "WebImage", class: "fieldValueContents" }).append( | |
textInputWithLabel("url", "Image url: ", "Image url input box") | |
), | |
$("<tr/>").append(textInputWithLabel("altText", "[Recommended] Alt-text: ", "Alt-text input box")) | |
]; | |
} | |
function formattedNumberContent(): JQuery<HTMLElement>[] { | |
return [ | |
$("<tr/>", { id: "FormattedNumber", class: "fieldValueContents" }).append( | |
textInputWithLabel("number", "Number: ", "Number input box") | |
), | |
$("<tr/>").append(textInputWithLabel("format", "Format: ", "Format input box")) | |
]; | |
} | |
function unsupportedContent(): JQuery<HTMLElement> { | |
return $("<tr/>", { id: "Unsupported", class: "fieldValueContents" }) | |
.append($("<td/>").append($("<label/>", { for: "unsupportedValue", class: "labels" }).text("unsupportedValue: "))) | |
.append( | |
$("<td/>").append( | |
$("<input>", { | |
class: "inputBox unsupportedValue", | |
disabled: true, | |
type: "text", | |
name: "unsupportedValue", | |
id: "unsupportedValue", | |
alt: "unsupportedValue input box" | |
}) | |
) | |
); | |
} | |
function createOptionsFromList(list: string[]): JQuery<HTMLElement>[] { | |
var options = []; | |
list.forEach(function(val) { | |
const noSpaceVal = val.replace(" ", ""); | |
options.push($("<option/>", { class: "type" + noSpaceVal, value: noSpaceVal }).text(val)); | |
}); | |
return options; | |
} | |
function specificFieldContent(): JQuery<HTMLElement> { | |
var content = entityContents(defaultType); | |
var select = $("<select/>", { | |
id: "dataTypeSelectEntity", | |
name: "dataType", | |
class: "dataTypeSelectEntity ms-Button ms-Button-label buttons", | |
style: "display:block" | |
}); | |
select[0].onchange = function() { | |
var options = (select[0] as HTMLSelectElement).options; | |
var valueType = options.item(options.selectedIndex).value; | |
$(content) | |
.children() | |
.replaceWith(entityContents(valueType).children()); | |
}; | |
var options = createOptionsFromList(["String", "Double", "Boolean", "Web Image", "Formatted Number"]); | |
for (var i = 0; i < options.length; ++i) { | |
select.append(options[i]); | |
} | |
select.append($("<option/>", { class: "typeUnsupported", value: "Unsupported", disabled: true }).text("Unsupported")); | |
var table = $("<table/>", { id: "fieldTable" }).append( | |
$("<tbody/>").append($("<tr/>").append($("<td/>").append(select))) | |
); | |
return $("<div/>", { id: "specificField", class: "specificFieldContents formContents solidBorder" }) | |
.append(table) | |
.append(content); | |
} | |
function entitySectionContent(): JQuery<HTMLElement> { | |
var fields = $(`<div class="fields"/>`).append(specificFieldContent()); | |
var section = $(`<div class="collapsibleSection" aria-expanded="true"/>`).append(fields); | |
var newFieldButton = $("<button/>", { | |
id: "addField", | |
class: "ms-Button ms-Button-label buttons", | |
alt: "add another field to current section", | |
style: "margin-left:20px;" | |
}).text("Add another field"); | |
/** Add a new field to selected section in the entity contents */ | |
newFieldButton[0].onclick = function() { | |
$(fields).append(specificFieldContent()); | |
}; | |
section.append(newFieldButton); | |
return section; | |
} | |
function entityDefaultSection(): JQuery<HTMLElement> { | |
var defaultSection = $(`<div id="defaultSection" class="sectionContents formContents solidBorder"/>`); | |
var label = $("<label/>", { class: "sectionHeader" }).text("Default section: "); | |
defaultSection.append([label, entitySectionContent()]); | |
return defaultSection; | |
} | |
function entitySection(): JQuery<HTMLElement> { | |
var element = $("<div/>", { class: "sectionContents formContents solidBorder" }); | |
var table1 = $(` | |
<table id="sectionTable"> | |
<tbody> | |
<tr class="columnTitle"> | |
<td> | |
<button class="ms-Button ms-Button-label arrows" onclick="moveSectionUp(this)" alt="button to move section up" title="move section up">▲</button> | |
<button class="ms-Button ms-Button-label arrows" onclick="moveSectionDown(this)" alt="button to move section down" title="move section down">▼</button> | |
</td> | |
<td><label class="sectionHeader">Section Title:</label></td> | |
<td><input class="inputBox sectionTitle" alt="section title input box"/></td> | |
<td> | |
<button class="ms-Button ms-Button-label arrows sectionToggle" onclick="collapseSection(this)" alt="collapse section" title="collapse section" style="visibility:visible">∨</button> | |
</td> | |
</tr> | |
</tbody> | |
</table>`); | |
var removeSectionButton = $("<button/>", { | |
class: "ms-Button ms-Button-label buttons", | |
alt: "delete current section and its contents" | |
}).text("Delete Section and its Contents"); | |
/** Remove the selected section in the entity contents */ | |
removeSectionButton[0].onclick = function() { | |
$(element).remove(); | |
}; | |
element.append(table1); | |
element.append(entitySectionContent().append(removeSectionButton)); | |
return element; | |
} | |
/** When data type is selected */ | |
$(document).ready(function() { | |
$("#dataTypeSelect").change(function() { | |
var value = $("#dataTypeSelect option:selected"); | |
setSelectedType(getTypeContent(value.val().toString())); | |
}); | |
setSelectedType(getTypeContent(defaultType)); | |
}); | |
function getTypeContent(valueType: string): JQuery<HTMLElement> | | |
JQuery<HTMLElement>[] { | |
switch (valueType) { | |
case "String": | |
return stringContent(); | |
case "Double": | |
return doubleContent(); | |
case "Boolean": | |
return booleanContent(); | |
case "FormattedNumber": | |
return formattedNumberContent(); | |
case "WebImage": | |
return webImageContent(); | |
case "Entity": | |
return entityContent(); | |
case "Unsupported": | |
default: | |
return unsupportedContent(); | |
} | |
} | |
/** Html for entity contents section */ | |
function entityContents(valueType: string): JQuery<HTMLElement> { | |
var trKey = $(`<tr> | |
<td rowspan="3"> | |
<button class="ms-Button ms-Button-label arrows" onclick="moveFieldUp(this)" alt="button to move field up" title="move field up">▲</button> | |
<button class="ms-Button ms-Button-label arrows" onclick="moveFieldDown(this)" alt="button to move field down" title="move field down">▼</button> | |
</td> | |
<td><label class="labels">Key:</label></td> | |
<td><input class="inputBox fieldName" alt="key input box"/></td> | |
</tr>`); | |
var tdMetadata = $(`<td colspan="4" class="center settings"/>`); | |
if (valueType == "WebImage") { | |
tdMetadata.append(checkboxWithLabel("mainImage", "Make Main Image", "main image checkbox")); | |
tdMetadata.append($("<br/>")); | |
} | |
tdMetadata.append([ | |
checkboxWithLabel("cardView", "Card View", "cardview checkbox"), | |
checkboxWithLabel("autoComplete", "Autocomplete", "autoComplete checkbox"), | |
$("<br/>"), | |
checkboxWithLabel("calcCompare", "Calc Compare", "calcCompare checkbox"), | |
checkboxWithLabel("dotNotation", "Dot Notation", "dotNotation checkbox"), | |
$("<br/>"), | |
$("<label/>").text("Sublabel: "), | |
$("<input/>", { class: "sublabel", alt: "sublabel input box" }) | |
]); | |
var trMetadata = $(`<tr class="metadata" style="visibility:collapse"/>`).append(tdMetadata); | |
var trButtons = $(`<tr/>`); | |
var tdButtons = $(`<td colspan="4"/>`); | |
var buttonRemoveField = $( | |
`<button class="ms-Button ms-Button-label buttons" onclick="removeField(this)" alt="delete current field">Delete Field</button>` | |
); | |
var buttonToggleMetadata = $( | |
`<button class="ms-Button ms-Button-label buttons" alt="toggle to expand or collapse metadata properties of field">More Settings</button>` | |
); | |
/** Function for expanding or collapsing additional metadata contents of a | |
particular input field in the entity contents */ | |
buttonToggleMetadata[0].onclick = function() { | |
var visibility = trMetadata[0].style.visibility; | |
if (visibility != "collapse") { | |
trMetadata[0].style.visibility = "collapse"; | |
} else { | |
trMetadata[0].style.visibility = "visible"; | |
} | |
}; | |
tdButtons.append([buttonRemoveField, buttonToggleMetadata]); | |
trButtons.append(tdButtons); | |
return $(`<div id="entityContents"/>`).append( | |
$(`<table id="fieldTable"/>`).append( | |
$(`<tbody/>`) | |
.append(trKey) | |
.append(getTypeContent(valueType)) | |
.append([trMetadata, trButtons]) | |
) | |
); | |
} | |
/** Html for type entity */ | |
function entityContent(): JQuery<HTMLElement> { | |
var div = $(`<div class="contentPadding"/>`); | |
var iconlabel = $(`<label class="labels"> Entity Icon: </label>`); | |
var contentLabel = $(`<label class="labels contentPadding">Entity Contents:</label>`); | |
var select = $(`<select id="iconSelect" name="dataType" class="ms-Button ms-Button-label buttons"/>`); | |
var options = createOptionsFromList([ | |
"Generic", | |
"Airplane", | |
"Animal", | |
"Apple", | |
"Art", | |
"Atom", | |
"Bank", | |
"Basketball", | |
"Beaker", | |
"Bird", | |
"Book", | |
"Bridge", | |
"Briefcase", | |
"Car", | |
"Cat", | |
"City", | |
"Clouds", | |
"Constellation", | |
"Dinosaur", | |
"Disaster", | |
"DNA", | |
"Dog", | |
"Drama", | |
"Galaxy", | |
"HatGraduation", | |
"Heart", | |
"Languages", | |
"Leaf", | |
"Location", | |
"Map", | |
"Microscope", | |
"Money", | |
"Mountain", | |
"MovieCamera", | |
"MusicNote", | |
"Notebook", | |
"PartlySunnyWeather", | |
"Person", | |
"Planet", | |
"PointScan", | |
"Running", | |
"Satellite", | |
"Syringe", | |
"Violin", | |
"Wand" | |
]); | |
for (var i = 0; i < options.length; ++i) { | |
select.append(options[i]); | |
} | |
div.append(iconlabel); | |
div.append(select); | |
var sections = $(`<div class="sections"/>`).append(entityDefaultSection()) | |
var label = $(`<label for="displayString" class="labels">Entity Display Text: </label>`); | |
var input = $(`<input class="inputBox displayString" type="text" id="displayString" alt="display text input box"/>`); | |
var providerTable = $(`<div id="entityContents" class="solidBorder formContents"/>`).append( | |
$(`<table id="fieldTable"/>`).append( | |
$(`<tbody/>`) | |
.append( | |
$("<tr/>").append( | |
textInputWithLabel("providerDescription", "Description: ", "Provider description input box") | |
) | |
) | |
.append( | |
$("<tr/>").append(textInputWithLabel("providerTarget", "Provider address: ", "Provider source input box")) | |
) | |
.append($("<tr/>").append(textInputWithLabel("providerLogo", "Logo address: ", "Provider logo input box"))) | |
) | |
); | |
var referencedValuesLabel = $(`<label for="referencedValues" class="labels">Referenced values: </label>`); | |
var referencedValuesInput = $( | |
`<input class="inputBox displayString" type="text" id="referencedValues" alt="referencedValues text isplay box" disabled/>` | |
); | |
var referencedValuesClearButton = $("<button/>", { | |
id: "clearReferencedValue", | |
class: "ms-Button ms-Button-label buttons", | |
text: "Clear referencedValues" | |
}); | |
var referencedValuesDiv = $("<div/>", { id: "referencedValuesDiv" }) | |
.append(referencedValuesLabel) | |
.append(referencedValuesInput) | |
.append(referencedValuesClearButton); | |
referencedValuesDiv[0].style.display = "none"; | |
referencedValuesClearButton[0].onclick = function() { | |
referencedValuesInput.val(""); | |
referencedValuesDiv[0].style.display = "none"; | |
}; | |
var collapseProviderInfo = $("<button/>", { | |
class: "ms-Button ms-Button-label sectionToggle arrows", | |
alt: "collapse section", | |
title: "collapse section" | |
}).text("\u2228"); | |
collapseProviderInfo[0].onclick = function() { | |
if (providerTable[0].style.display == "none") { | |
providerTable[0].style.display = "block"; | |
collapseProviderInfo.text("\u2228"); | |
collapseProviderInfo[0].setAttribute("alt", "collapse section"); | |
collapseProviderInfo[0].setAttribute("title", "collapse section"); | |
} else { | |
providerTable[0].style.display = "none"; | |
collapseProviderInfo.text("\u2227"); | |
collapseProviderInfo[0].setAttribute("alt", "expand section"); | |
collapseProviderInfo[0].setAttribute("title", "expand section"); | |
} | |
}; | |
var providerInfo = $("<div/>", { class: "contentPadding" }) | |
.append($("<label/>", { class: "labels" }).text("Provider info: ")) | |
.append(collapseProviderInfo) | |
.append(providerTable); | |
var element = $(`<tr id="Entity"/>`).append( | |
$(`<td colspan="2"/>`) | |
.append([label, input]) | |
.append(div) | |
.append(providerInfo) | |
.append(referencedValuesDiv) | |
.append(contentLabel) | |
.append(sections) | |
.append( | |
$( | |
`<button id="addSection" onclick="addSection()" class="ms-Button ms-Button-label buttons" style="margin-left:20px;" alt="add another section to entity contents">Add another section</button>` | |
) | |
) | |
); | |
return element; | |
} | |
/** Html for when boolean, string or double are selected */ | |
function setSelectedType(selected: JQuery<HTMLElement>[] | | |
JQuery<HTMLElement>) { | |
var element = $(`<div class= "backgroundColorForm solidBorder"/>`); | |
element.append(selected); | |
$(".backgroundColorForm").replaceWith(element); | |
} | |
/** Add another section in entity contents */ | |
function addSection() { | |
$(".sections").append(entitySection()); | |
} | |
/** Add a new field to the entity contents */ | |
function addField(element: HTMLButtonElement) { | |
//append specificFieldContents to fields div | |
const fieldsDiv = element.parentElement.previousElementSibling; | |
$(fieldsDiv).append(specificFieldContent()); | |
} | |
/** Move a field down in the entity contents order */ | |
function moveFieldDown(element: HTMLButtonElement) { | |
const curSpecificField = element.parentElement.parentElement.parentElement.parentElement.parentElement | |
.parentElement as HTMLDivElement; | |
const nextSpecificField = curSpecificField.nextElementSibling as HTMLDivElement; | |
if (nextSpecificField) { | |
$(curSpecificField).remove(); | |
$(nextSpecificField).after(curSpecificField); | |
} else { | |
const curSectionContents = curSpecificField.parentElement.parentElement.parentElement as HTMLDivElement; | |
const nextSectionContents = curSectionContents.nextElementSibling as HTMLDivElement; | |
if (nextSectionContents) { | |
const nextSectionFields = $(nextSectionContents).find(".fields"); | |
$(curSpecificField).remove(); | |
nextSectionFields.prepend(curSpecificField); | |
} | |
} | |
} | |
/** Move a section down in the entity contents order */ | |
function moveSectionDown(element: HTMLButtonElement) { | |
const curSpecificSection = element.parentElement.parentElement.parentElement.parentElement | |
.parentElement as HTMLDivElement; | |
const nextSpecificSection = curSpecificSection.nextElementSibling as HTMLDivElement; | |
if (nextSpecificSection) { | |
$(curSpecificSection).remove(); | |
$(nextSpecificSection).after(curSpecificSection); | |
} | |
} | |
/** Move a field up in the entity contents order */ | |
function moveFieldUp(element: HTMLButtonElement) { | |
const curSpecificField = element.parentElement.parentElement.parentElement.parentElement.parentElement | |
.parentElement as HTMLDivElement; | |
const prevSpecificField = curSpecificField.previousElementSibling as HTMLDivElement; | |
if (prevSpecificField) { | |
$(curSpecificField).remove(); | |
$(prevSpecificField).before(curSpecificField); | |
} else { | |
const curSectionContents = curSpecificField.parentElement.parentElement.parentElement as HTMLDivElement; | |
const prevSectionContents = curSectionContents.previousElementSibling as HTMLDivElement; | |
if (prevSectionContents) { | |
const prevSectionFields = $(prevSectionContents).find(".fields"); | |
$(curSpecificField).remove(); | |
prevSectionFields.append(curSpecificField); | |
} | |
} | |
} | |
/** Move a section up in the entity contents order */ | |
function moveSectionUp(element: HTMLButtonElement) { | |
const curSpecificSection = element.parentElement.parentElement.parentElement.parentElement | |
.parentElement as HTMLDivElement; | |
const prevSpecificSection = curSpecificSection.previousElementSibling as HTMLDivElement; | |
if (prevSpecificSection && prevSpecificSection.id != "defaultSection") { | |
$(curSpecificSection).remove(); | |
$(prevSpecificSection).before(curSpecificSection); | |
} | |
} | |
/** Function for expanding section contents in the entity contents */ | |
function expandSection(element: HTMLButtonElement) { | |
element.parentElement.parentElement.parentElement.parentElement.nextElementSibling.style.display = "block"; | |
$(element).replaceWith( | |
`<button class="ms-Button ms-Button-label arrows sectionToggle" onclick="collapseSection(this)" alt="collapse section" title="collapse section">∨</button>` | |
); | |
} | |
/** Function for collapsing section contents in the entity contents */ | |
function collapseSection(element: HTMLButtonElement) { | |
element.parentElement.parentElement.parentElement.parentElement.nextElementSibling.style.display = "none"; | |
$(element).replaceWith( | |
`<button class="ms-Button ms-Button-label arrows sectionToggle" onclick="expandSection(this)" alt="expand section" title="expand section" >∧ </button>` | |
); | |
} | |
/** Function for printing the inputted data into the console */ | |
function printAsJson() { | |
console.log(JSON.stringify(createValueAsJson())); | |
} | |
/** Function for assigning the inputted data to the active cell as the | |
appropriate data type */ | |
function createValueAsJson(): Excel.CellValue { | |
var values = $("#dataTypeSelect option:selected"); | |
switch (values.val()) { | |
case "String": | |
var stringValue = $("#basicValue") | |
.val() | |
.toString(); | |
return { | |
type: Excel.CellValueType.string, | |
basicValue: stringValue | |
} as Excel.StringCellValue; | |
case "Double": | |
var doubleValue = Number($("#basicValue").val()); | |
if (!isNaN(doubleValue)) { | |
return { | |
type: Excel.CellValueType.double, | |
basicValue: doubleValue | |
} as Excel.DoubleCellValue; | |
} else { | |
alert("Type 'Double' selected but input was not a double."); | |
} | |
break; | |
case "Boolean": | |
var booleanValue = $("#basicValue") | |
.val() | |
.toString(); | |
if (booleanValue.toLowerCase() === "true") { | |
return { | |
type: Excel.CellValueType.boolean, | |
basicValue: true | |
} as Excel.BooleanCellValue; | |
} else if (booleanValue.toLowerCase() === "false") { | |
return { | |
type: Excel.CellValueType.boolean, | |
basicValue: false | |
} as Excel.BooleanCellValue; | |
} else { | |
alert("Type 'Boolean' selected but input was not a boolean."); | |
} | |
break; | |
case "Entity": | |
return setEntity(); | |
case "WebImage": | |
var url = $("#url") | |
.val() | |
.toString(); | |
var altText = $("#altText") | |
.val() | |
.toString(); | |
return { | |
type: Excel.CellValueType.webImage, | |
address: url, | |
altText: altText | |
}; | |
case "FormattedNumber": | |
var doubleValue = Number($("#number").val()); | |
var format = $("#format").val(); | |
if (!isNaN(doubleValue)) { | |
return { | |
type: Excel.CellValueType.formattedNumber, | |
basicValue: doubleValue, | |
numberFormat: format | |
} as Excel.FormattedNumberCellValue; | |
} else { | |
alert("Type 'FormattedNumber' selected but input was not a number."); | |
} | |
break; | |
} | |
} | |
async function setData() { | |
await Excel.run(async (context) => { | |
const activeCell = context.workbook.getActiveCell(); | |
activeCell.valuesAsJson = [[createValueAsJson()]]; | |
await tryCatch(context.sync); | |
}); | |
} | |
/** Function for assigning the inputted entity contents to an entity */ | |
function setEntity() { | |
const display: string = $("#displayString") | |
.val() | |
.toString(); | |
var iconName: string = $("#iconSelect option:selected").val() as string; | |
const referencedValues: string = $("#referencedValues").val() as string; | |
const fields = valuesFromQuery(".fieldName"); | |
const values = fieldValuesContentsFromQuery(); | |
const cardViews = valuesFromQuery(".cardView"); | |
const autoCompletes = valuesFromQuery(".autoComplete"); | |
const calcCompares = valuesFromQuery(".calcCompare"); | |
const dotNotation = valuesFromQuery(".dotNotation"); | |
const sublabels = valuesFromQuery(".sublabel"); | |
var mainImage = valuesFromQuery(".mainImage"); | |
var providerInfo = [ | |
valuesFromQuery("#providerDescription"), | |
valuesFromQuery("#providerTarget"), | |
valuesFromQuery("#providerLogo") | |
]; | |
var mainImageExists = false; | |
var mainImageKey; | |
var sectionArray = []; | |
var jqSectionContents = $(".sectionContents"); | |
var fDefaultSection: Boolean = true; | |
while (jqSectionContents.length > 0) { | |
const first = jqSectionContents.first(); | |
var children = first.find(".fieldName"); | |
var sectionTitle = first.find(".sectionTitle"); | |
var properties = []; | |
for (var i = 0; i < children.length; ++i) { | |
var val = $(children[i]).val(); | |
properties.push(val); | |
} | |
// first section is the default; Not really a section | |
if (fDefaultSection) { | |
fDefaultSection = false; | |
jqSectionContents = jqSectionContents.slice(1); | |
continue; | |
} | |
var sectionEntry = { | |
layout: "List", | |
title: sectionTitle.val(), | |
properties: properties | |
}; | |
sectionArray.push(sectionEntry); | |
jqSectionContents = jqSectionContents.slice(1); | |
} | |
var entity: Excel.EntityCellValue = { | |
type: Excel.CellValueType.entity, | |
text: display, | |
properties: {}, | |
layouts: { | |
card: {}, | |
compact: {} | |
} | |
}; | |
if (providerInfo[0][0] != "" || providerInfo[1][0] != "" || providerInfo[2][0] != "") { | |
entity.provider = { | |
description: providerInfo[0][0], | |
logoTargetAddress: providerInfo[1][0], | |
logoSourceAddress: providerInfo[2][0] | |
}; | |
} | |
for (var i = 0; i < fields.length; ++i) { | |
var curSectionFields = []; | |
const field = fields[i]; | |
var value = values[i]; | |
if (field == "" || value == "") { | |
break; | |
} | |
var featureIntegration = {}; | |
if (!cardViews[i]) { | |
featureIntegration["cardView"] = true; | |
} | |
if (!autoCompletes[i]) { | |
featureIntegration["autoComplete"] = true; | |
} | |
if (!calcCompares[i]) { | |
featureIntegration["calcCompare"] = true; | |
} | |
if (!dotNotation[i]) { | |
featureIntegration["dotNotation"] = true; | |
} | |
var propertyMetadata = {}; | |
if (Object.keys(featureIntegration).length > 0) { | |
propertyMetadata["excludeFrom"] = featureIntegration; | |
} | |
if (sublabels[i] != "") { | |
propertyMetadata["sublabel"] = sublabels[i]; | |
} | |
if (value.type == "WebImage") { | |
if (mainImage[0] && !mainImageExists) { | |
mainImageKey = field; | |
mainImageExists = true; | |
} | |
mainImage = mainImage.slice(1); | |
} | |
if (Object.keys(propertyMetadata).length > 0) { | |
value["propertyMetadata"] = propertyMetadata; | |
} | |
entity.properties[field] = value; | |
} | |
if (mainImageExists) { | |
entity.layouts.card = { | |
mainImage: { | |
property: mainImageKey | |
}, | |
sections: sectionArray | |
}; | |
} else { | |
entity.layouts.card = { | |
sections: sectionArray | |
}; | |
} | |
//addCachedRefs(entity); | |
if (referencedValues != "") { | |
entity.referencedValues = JSON.parse(referencedValues); | |
} | |
if (iconName != "Generic") { | |
entity.layouts.compact["icon"] = iconName; | |
} | |
return entity; | |
} | |
/** Helper Function for retrieving jquery values for setEntity() */ | |
function valuesFromQuery(query: string) { | |
var jq = $(query); | |
var result = []; | |
while (jq.length > 0) { | |
const first = jq.first(); | |
if (first.is("input[type=checkbox]")) { | |
result.push(first.prop("checked")); | |
} else { | |
result.push(first.val()); | |
} | |
jq = jq.slice(1); | |
} | |
return result; | |
} | |
/** Helper Function for retrieving fieldValue contents for jquery for | |
setEntity() */ | |
function fieldValuesContentsFromQuery() { | |
var jqFieldContents = $(".fieldValueContents"); | |
var jqBasicValue = $(".basicValue"); | |
var jqUrl = $(".url"); | |
var jqNumber = $(".number"); | |
var jqFormat = $(".format"); | |
var jqAltText = $(".altText"); | |
var jqUnsupportedValue = $(".unsupportedValue"); | |
var values = []; | |
while (jqFieldContents.length > 0) { | |
const first = jqFieldContents.first(); | |
var valueType = first.attr("id"); | |
var value; | |
switch (valueType) { | |
case "String": | |
value = { | |
type: Excel.CellValueType.string, | |
basicValue: jqBasicValue | |
.first() | |
.val() | |
.toString() | |
} as Excel.StringCellValue; | |
jqBasicValue = jqBasicValue.slice(1); | |
break; | |
case "FormattedNumber": | |
var doubleValue = Number(jqNumber.first().val()); | |
if (!isNaN(doubleValue)) { | |
value = { | |
type: Excel.CellValueType.formattedNumber, | |
basicValue: doubleValue, | |
numberFormat: jqFormat | |
.first() | |
.val() | |
.toString() | |
}; | |
} else { | |
alert("Type 'FormattedNumber' selected but input was not a number."); | |
} | |
jqNumber = jqNumber.slice(1); | |
jqFormat = jqFormat.slice(1); | |
break; | |
case "Double": | |
var doubleValue = Number(jqBasicValue.first().val()); | |
if (!isNaN(doubleValue)) { | |
value = { | |
type: Excel.CellValueType.double, | |
basicValue: doubleValue | |
} as Excel.DoubleCellValue; | |
} else { | |
alert("Type 'Double' selected but input was not a double."); | |
} | |
jqBasicValue = jqBasicValue.slice(1); | |
break; | |
case "Boolean": | |
var booleanValue = jqBasicValue | |
.first() | |
.val() | |
.toString(); | |
if (booleanValue.toLowerCase() === "true") { | |
value = { | |
type: Excel.CellValueType.boolean, | |
basicValue: true | |
} as Excel.BooleanCellValue; | |
} else if (booleanValue.toLowerCase() === "false") { | |
value = { | |
type: Excel.CellValueType.boolean, | |
basicValue: false | |
} as Excel.BooleanCellValue; | |
} else { | |
alert("Type 'Boolean' selected but input was not a boolean."); | |
} | |
jqBasicValue = jqBasicValue.slice(1); | |
break; | |
case "WebImage": | |
value = { | |
type: Excel.CellValueType.webImage, | |
address: jqUrl.first().val(), | |
altText: jqAltText.first().val() | |
} as Excel.WebImageCellValue; | |
jqUrl = jqUrl.slice(1); | |
jqAltText = jqAltText.slice(1); | |
break; | |
case "Unsupported": | |
value = JSON.parse( | |
jqUnsupportedValue | |
.first() | |
.val() | |
.toString() | |
); | |
jqUnsupportedValue = jqUnsupportedValue.slice(1); | |
break; | |
} | |
values.push(value); | |
jqFieldContents = jqFieldContents.slice(1); | |
} | |
return values; | |
} | |
/** Function for removing a selected input field in the entity contents */ | |
function removeField(element: HTMLButtonElement) { | |
// removes specificField | |
element.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.remove(); | |
} | |
/** Function for retrieving the contents of a selected entity and putting | |
them in the form boxes */ | |
function getEntity(value) { | |
var sections; | |
if (value.layouts != undefined && value.layouts.card != undefined) { | |
sections = value.layouts.card.sections; | |
} | |
// If there is no section, make one | |
if (sections == undefined) { | |
const propertyKeys = Object.keys(value.properties); | |
sections = [ | |
{ | |
layout: "List", | |
properties: propertyKeys | |
} | |
]; | |
} | |
if (value.referencedValues != undefined) { | |
$("#referencedValues").val(JSON.stringify(value.referencedValues)); | |
$("#referencedValuesDiv")[0].style.display = "block"; | |
} else { | |
$("#clearReferencedValue")[0].onclick(null); | |
} | |
if (value.provider != undefined) { | |
if (value.provider.description != undefined) { | |
$("#providerDescription").val(value.provider.description); | |
} | |
if (value.provider.description != undefined) { | |
$("#providerTarget").val(value.provider.logoTargetAddress); | |
} | |
if (value.provider.description != undefined) { | |
$("#providerLogo").val(value.provider.logoSourceAddress); | |
} | |
} | |
var propertyKeysOrdered = []; | |
for (var i = 0; i < sections.length; ++i) { | |
if (i != 0) { | |
addSection(); | |
} | |
$(".sectionTitle") | |
.last() | |
.val(sections[i].title); | |
var sectionKeys = sections[i].properties; | |
$(".specificFieldContents") | |
.last() | |
.remove(); | |
for (var j = 0; j < sectionKeys.length; ++j) { | |
$(".fields") | |
.last() | |
.append(specificFieldContent()); | |
const propertyName = sectionKeys[j]; | |
propertyKeysOrdered.push(propertyName); | |
const propertyValue = value.properties[propertyName]; | |
const entityContentsDiv = $(".dataTypeSelectEntity") | |
.last() | |
.parent() | |
.parent() | |
.parent() | |
.parent() | |
.next() | |
.children(); | |
switch (propertyValue.type) { | |
case "Double": | |
$(".dataTypeSelectEntity") | |
.last() | |
.val("Double"); | |
entityContentsDiv.replaceWith(entityContents(propertyValue.type).children()); | |
break; | |
case "Boolean": | |
$(".dataTypeSelectEntity") | |
.last() | |
.val("Boolean"); | |
entityContentsDiv.replaceWith(entityContents(propertyValue.type).children()); | |
break; | |
case "FormattedNumber": | |
$(".dataTypeSelectEntity") | |
.last() | |
.val("FormattedNumber"); | |
entityContentsDiv.replaceWith(entityContents(propertyValue.type).children()); | |
break; | |
case "WebImage": | |
$(".dataTypeSelectEntity") | |
.last() | |
.val("WebImage"); | |
entityContentsDiv.replaceWith(entityContents(propertyValue.type).children()); | |
const firstMetadataElement = $(".cardView") | |
.last() | |
.parent(); | |
firstMetadataElement.before(`<div class="checkboxes"> | |
<input type="checkbox" class="mainImage" alt="main image checkbox"/> | |
<label>Make Main Image</label> | |
</div><br>`); | |
break; | |
case "String": | |
$(".dataTypeSelectEntity") | |
.last() | |
.val("String"); | |
entityContentsDiv.replaceWith(entityContents(propertyValue.type).children()); | |
break; | |
default: | |
/*unsupported*/ | |
$(".dataTypeSelectEntity") | |
.last() | |
.val("Unsupported"); | |
entityContentsDiv.replaceWith(entityContents("Unsupported").children()); | |
break; | |
} | |
} | |
} | |
// write the entity's data into the table | |
$("#displayString").val(value.text); | |
if (value.layouts == undefined || value.layouts.compact == undefined) $("#iconSelect").val("Generic"); | |
else if (value.layouts.compact["icon"] != undefined) { | |
$("#iconSelect").val(value.layouts.compact["icon"]); | |
} | |
var jqFields = $(".fieldName"); | |
var jqCardView = $(".cardView"); | |
var jqAutoComplete = $(".autoComplete"); | |
var jqCalcCompare = $(".calcCompare"); | |
var jqDotNotation = $(".dotNotation"); | |
var jqSublabel = $(".sublabel"); | |
var jqBasicValue = $(".basicValue"); | |
var jqUrl = $(".url"); | |
var jqNumber = $(".number"); | |
var jqFormat = $(".format"); | |
var jqAltText = $(".altText"); | |
var jqMainImage = $(".mainImage"); | |
var jqUnsupportedValue = $(".unsupportedValue"); | |
for (var i = 0; i < propertyKeysOrdered.length; ++i) { | |
const propertyName = propertyKeysOrdered[i]; | |
const propertyValue = value.properties[propertyName]; | |
jqFields.first().val(propertyName); | |
switch (propertyValue.type) { | |
case "Double": | |
case "Boolean": | |
case "String": | |
jqBasicValue.first().val(propertyValue.basicValue); | |
jqBasicValue = jqBasicValue.slice(1); | |
break; | |
case "WebImage": | |
jqUrl.first().val(propertyValue.address); | |
jqAltText.first().val(propertyValue.altText); | |
jqUrl = jqUrl.slice(1); | |
jqAltText = jqAltText.slice(1); | |
if (value.layouts != undefined) | |
if (value.layouts.card["mainImage"] != undefined) { | |
if (value.layouts.card.mainImage.property == propertyName) { | |
jqMainImage.first().prop("checked", true); | |
} | |
} | |
break; | |
case "FormattedNumber": | |
jqNumber.first().val(propertyValue.basicValue); | |
jqFormat.first().val(propertyValue.numberFormat); | |
jqNumber = jqNumber.slice(1); | |
jqFormat = jqFormat.slice(1); | |
break; | |
default: | |
jqUnsupportedValue.first().val(JSON.stringify(propertyValue)); | |
jqUnsupportedValue = jqUnsupportedValue.slice(1); | |
break; | |
} | |
var featureIntegration: Excel.CellValuePropertyMetadataExclusions = { | |
cardView: false, | |
autoComplete: false, | |
calcCompare: false, | |
dotNotation: false | |
}; | |
var sublabel = ""; | |
if (typeof propertyValue.propertyMetadata == "object") { | |
if (typeof propertyValue.propertyMetadata.excludeFrom == "object") { | |
featureIntegration = Object.assign(featureIntegration, propertyValue.propertyMetadata.excludeFrom); | |
} | |
if (typeof propertyValue.propertyMetadata.sublabel == "string") { | |
sublabel = propertyValue.propertyMetadata.sublabel; | |
} | |
} | |
jqCardView.first().prop("checked", !featureIntegration.cardView); | |
jqAutoComplete.first().prop("checked", !featureIntegration.autoComplete); | |
jqCalcCompare.first().prop("checked", !featureIntegration.calcCompare); | |
jqDotNotation.first().prop("checked", !featureIntegration.dotNotation); | |
jqSublabel.first().val(sublabel); | |
jqFields = jqFields.slice(1); | |
jqCardView = jqCardView.slice(1); | |
jqAutoComplete = jqAutoComplete.slice(1); | |
jqCalcCompare = jqCalcCompare.slice(1); | |
jqDotNotation = jqDotNotation.slice(1); | |
jqSublabel = jqSublabel.slice(1); | |
} | |
} | |
/** Function for retrieving the contents of a selected cell and putting them | |
in the form boxes */ | |
async function getData() { | |
await Excel.run(async (context) => { | |
const activeCell = context.workbook.getActiveCell(); | |
activeCell.load("valuesAsJson"); | |
await context.sync(); | |
const value = activeCell.valuesAsJson[0][0]; | |
clearForm(); | |
var valueType = value.type == "LinkedEntity" ? "Entity" : value.type; | |
$("#dataTypeSelect").val(valueType); | |
setSelectedType(getTypeContent(valueType)); | |
switch (value.type) { | |
case "String": | |
$("#basicValue").val(value.basicValue); | |
break; | |
case "Double": | |
$("#basicValue").val(value.basicValue); | |
break; | |
case "Boolean": | |
const basicValue = value.basicValue; | |
if (basicValue) { | |
$("#basicValue").val("true"); | |
} else { | |
$("#basicValue").val("false"); | |
} | |
break; | |
case "WebImage": | |
$("#url").val(value.address); | |
$("#altText").val(value.altText); | |
break; | |
case "FormattedNumber": | |
$("#format").val(value.numberFormat); | |
$("#number").val(value.basicValue); | |
break; | |
case "Entity": | |
case "LinkedEntity": | |
getEntity(value); | |
break; | |
} | |
}); | |
} | |
/** Function for clearing the input boxes */ | |
async function clearForm() { | |
$(".inputBox").val(""); | |
$(".cardView").prop("checked", true); | |
$(".autoComplete").prop("checked", true); | |
$(".calcCompare").prop("checked", true); | |
$(".dotNotation").prop("checked", true); | |
$(".mainImage").prop("checked", false); | |
$(".sublabel").val(""); | |
$(".specificFieldContents").remove(); | |
$(".sectionContents").remove(); | |
$("#iconSelect").val("Generic"); | |
setSelectedType( | |
getTypeContent( | |
$("#dataTypeSelect") | |
.val() | |
.toString() | |
) | |
); | |
} | |
/** Default helper for invoking an action and handling errors. */ | |
async function tryCatch(callback) { | |
try { | |
await callback(); | |
} catch (error) { | |
alert("Error in running script:\n\n" + error + "."); | |
console.error(error); | |
} | |
} | |
language: typescript | |
template: | |
content: "<section class=\"ms-font-m main\">\n\t<h1>\n\t\tCreate and Retrieve Data\n\t</h1>\n\t<p>\n\t\tChoose the type of data you want to insert from the dropdown below or select a cell and press <b>Get Data</b> to\n\t\tretrieve its data:\n\t</p>\n\n\t<div>\n\t\t<button id=\"getData\" onclick=\"getData()\" class=\"ms-Button ms-Button-label buttons\">Get Data</button>\n\t\t<label> | </label>\n\t\t<button id=\"setData\" onclick=\"setData()\" class=\"ms-Button ms-Button-label buttons\" alt=\"set entered data into active cell\">Set</button>\n\t\t<button id=\"printAsJson\" onclick=\"printAsJson()\" class=\"ms-Button ms-Button-label buttons\" alt=\"print entered data as json into the console\">Print as Json</button>\n\t\t<label> | </label>\n\t\t<button id=\"clearForm\" onclick=\"clearForm()\" class=\"ms-Button ms-Button-label buttons\" alt=\"clear current contents of input boxes\">Clear</button>\n\t</div>\n\n\t<select id=\"dataTypeSelect\" name=\"dataType\" class=\"ms-Button ms-Button-label buttons\">\n\t\t\t\t<option class=\"typeString\" value=\"String\" selected>String</option>\n\t\t\t\t<option class=\"typeDouble\" value=\"Double\">Double</option>\n\t\t\t\t<option class=\"typeBoolean\" value=\"Boolean\">Boolean</option>\n\t\t\t\t<option class=\"typeEntity\" value=\"Entity\">Entity</option>\n\t\t\t\t<option class=\"typeImage\" value=\"WebImage\">Web Image</option>\n\t\t\t\t<option class=\"typeFNV\" value=\"FormattedNumber\">Formatted Number</option>\n\t\t\t</select>\n\n\t<div id=\"dataTypeContents\">\n\t\t<div class=\"backgroundColorForm solidBorder\">\n\t\t</div>\n\t</div>\n\n\t<div>\n\t\t<button id=\"getData\" onclick=\"getData()\" class=\"ms-Button ms-Button-label buttons\">Get Data</button>\n\t\t<label> | </label>\n\t\t<button id=\"setData\" onclick=\"setData()\" class=\"ms-Button ms-Button-label buttons\" alt=\"set entered data into active cell\">Set</button>\n\t\t<button id=\"printAsJson\" onclick=\"printAsJson()\" class=\"ms-Button ms-Button-label buttons\" alt=\"print entered data as json into the console\">Print as Json</button>\n\t\t<label> | </label>\n\t\t<button id=\"clearForm\" onclick=\"clearForm()\" class=\"ms-Button ms-Button-label buttons\" alt=\"clear current contents of input boxes\">Clear</button>\n\t</div>\n\n</section>\n\n<section class=\"ms-font-m main\">\n\t<br><a\n\t\thref=\"https://docs.microsoft.com/en-us/javascript/api/excel/excel.range?view=excel-js-preview#valuesAsJson\">Learn\n\t\tmore about valuesAsJson</a><br>\n</section>" | |
language: html | |
style: | |
content: |2- | |
section.samples .ms-Button, section.setup, .main { | |
display: block; | |
margin-bottom: 5px; | |
margin-left: 20px; | |
margin-right: 20px; | |
min-width: 50px; | |
} | |
.backgroundColorForm { | |
background-color: #E0E0E0; | |
padding: 20px 0px; | |
width: 560px; | |
} | |
.contentPadding { | |
padding: 0 10px; | |
} | |
.arrows { | |
background-color: #E0E0E0; | |
border-color: #E0E0E0; | |
margin: 0px; | |
min-width: 0px; | |
padding: 5px 5px; | |
/*display: block;*/ | |
} | |
.checkboxes { | |
display: inline; | |
} | |
.buttons { | |
margin: 10px; | |
} | |
.center { | |
text-align: center; | |
} | |
.centerObject { | |
margin: 5px auto; | |
} | |
.columnTitle { | |
text-align: center; | |
font-weight: bold; | |
} | |
.formContents { | |
margin: 5px 10px; | |
padding: 10px; | |
} | |
.solidBorder { | |
border-style: solid; | |
border-width: thin; | |
border-color: #C0C0C0; | |
border-radius: 5px; | |
} | |
.inputBox { | |
margin: 0px auto; | |
padding: 5px 2px; | |
min-width: 200px; | |
} | |
.labels { | |
margin: 2px 10px; | |
min-width: 175px; | |
font-weight: bold; | |
} | |
.sectionHeader { | |
display: block; | |
margin-left: 5px; | |
margin-right: 15px; | |
font-weight: bold; | |
} | |
.sectionTitle { | |
min-width: 290px; | |
} | |
.sectionToggle { | |
text-align: right; | |
padding: 10px 15px; | |
} | |
language: css | |
libraries: | | |
https://appsforoffice.microsoft.com/lib/beta/hosted/office.js | |
https://appsforoffice.microsoft.com/lib/beta/hosted/office.d.ts | |
office-ui-fabric-js@1.4.0/dist/css/fabric.min.css | |
office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css | |
core-js@2.4.1/client/core.min.js | |
@types/core-js | |
jquery@3.1.1 | |
@types/jquery@3.3.1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment