Trying to create a custom data connector for Power BI. Installed Visual Studio Code and imported the Power Query SDK extension. Created a new project which I called FirstConnector which creates a Hello World. Changed nothing. Ran it and it failed immediately.
I run the file FirstConnector.query.pq:
// Use this file to write queries to test your data connector
let
result = FirstConnector.Contents()
in
result
It calls the function in the file FirstConnector.pq:
// This file contains your Data Connector logic
[Version = "1.0.0"]
section FirstConnector;
[DataSource.Kind="FirstConnector", Publish="FirstConnector.Publish"]
shared FirstConnector.Contents = (optional message as text) =>
let
_message = if (message <> null) then message else "(no message)",
a = "Hello from FirstConnector: " & _message
in
a;
// Data Source Kind description
FirstConnector = [
Authentication = [
// Key = [],
// UsernamePassword = [],
// Windows = [],
Anonymous = []
]
];
// Data Source UI publishing description
FirstConnector.Publish = [
Beta = true,
Category = "Other",
ButtonText = { Extension.LoadString("ButtonTitle"), Extension.LoadString("ButtonHelp") },
LearnMoreUrl = "https://powerbi.microsoft.com/",
SourceImage = FirstConnector.Icons,
SourceTypeImage = FirstConnector.Icons
];
FirstConnector.Icons = [
Icon16 = { Extension.Contents("FirstConnector16.png"), Extension.Contents("FirstConnector20.png"), Extension.Contents("FirstConnector24.png"), Extension.Contents("FirstConnector32.png") },
Icon32 = { Extension.Contents("FirstConnector32.png"), Extension.Contents("FirstConnector40.png"), Extension.Contents("FirstConnector48.png"), Extension.Contents("FirstConnector64.png") }
];
Here are the execution messages:
Related
Does any one know how to use the V1Beta1 version in c#. It will be a great help if some one can point me to some example. Google has not created a Client for this version.
https://cloud.google.com/text-to-speech/docs/reference/rest/v1beta1/text/synthesize#TimepointType
I had the same problem (for Google.Apis.Texttospeech.v1) and could not find an example anywhere. I pieced it together from some Ruby Api docs, so, this works for me.
How to use Google.Apis.Texttospeech.v1 in C#:
var request = new Google.Apis.Texttospeech.v1.Data.SynthesizeSpeechRequest();
request.AudioConfig = new Google.Apis.Texttospeech.v1.Data.AudioConfig()
{
AudioEncoding = "Linear16" // = WAV, or "MP3", "OGG_OPUS"
};
request.Input = new Google.Apis.Texttospeech.v1.Data.SynthesisInput
{
Text = "Sample Speaker Text" // Or use Ssml = "<speak> Your SSML Text.
</speak>"
};
request.Voice = new Google.Apis.Texttospeech.v1.Data.VoiceSelectionParams
{
LanguageCode = "en-EN",
Name = "en-US-Wavenet-C"
};
var service = new Google.Apis.Texttospeech.v1.TexttospeechService(new
Google.Apis.Services.BaseClientService.Initializer
{
ApplicationName = "My Sample App",
ApiKey = "[Your API Key]"
}
);
var response = service.Text.Synthesize(request).Execute();
using (var output = System.IO.File.Create("audioclip.wav"))
{
var bytes = System.Convert.FromBase64String(response.AudioContent);
output.Write(bytes, 0, bytes.Length);
}
I have a requirement of adding Value to Custom attribute in G Suite for bulk users, I have added address and other field using App script but don't know how to add values to a custom attribute named "Enhanced Desktop Security" as shown in the image below.
Value to be added is using App Script is: "un:Windows"
Request your help with the Script.
I have been working on this and came to know that 1st you have to identify the schemas of the custom attribute here : https://developers.google.com/admin-sdk/directory/v1/reference/users/list Once you do that you can use the below script. Please make sure that you change the schema in the below script.
Mention "User Email ID", "Value", "Updation Status" in Cloumn A,B,C, respectively in sheet.
function updateCustomE() {
var ss = SpreadsheetApp.openById(""); // Mention ID of the spreadsheet here.
var sheet = ss.getSheetByName(""); // Mention Name of the sheet here.
var values = sheet.getDataRange().getValues();
var fileArray = [["Updation Status"]]
for(i=1; i <values.length; i++)
{
var userKey = values[i][0]
var customValue = values [i][1]
try{
var status = "Value not updated"
var status = AdminDirectory.Users.update({
"customSchemas": {
"Enhanced_desktop_security" : {
"Local_Windows_accounts" : [
{
"type": "custom",
"value": customValue
}
]
}
}
}, userKey);
if (status != "Value not updated"){
status = "Value updated Successfully"
}
}
catch (e) {
Logger.log(e.message)
var status = e.message
}
fileArray.push([status])
}
var range = sheet.getRange(1, 3, fileArray.length, 1).setValues(fileArray)
}
Where can I find code and instruction on how to allow users to upload files with Google Form without login?
I searched all over here and couldn't find any information.
https://developers.google.com/apps-script/reference
Thanks in advance.
The user will be uploading the files to your drive. So, google needs to verify the user. If there is no verification, someone can fill your drive in no time.
It is for your safety to know who has uploaded, so, login is must.
There's a workaround, I'm in a hurry to write the code now, but if you're interested let me know and I'll edit later.
Basically, you set up a web app with apps script, then you setup a custom HTML form, you'll have to manually collect the file, convert is to base64 then json, then when you catch it in apps script you reverse the process and save it wherever you want in your drive.
Since the user will be executing the script as you, there's no verification required
/*
These functions basically go through a file array and reads the files first as binary string (in second function), then converts the files to base64 string (func 1) before stringifying the files (after putting their base64 content into an object with other metadata attached; mime, name e.t.c);
You pass this stringified object into the body part of fetch(request,{body:"stringified object goes here"})
see next code block for how to read in apps script and save the files to google drive
N.B. The body data will be available under doPost(e){e.postData.contents}
*/
async function bundleFilesForUpload(){
let filesDataObj = [];
let copy = {fileInfo:{"ogname":"","meme":""},fileData:""};
for(let i = 0 ; i < counters.localVar.counters.filesForUploadArr.length ; i++){
let tempObj = JSON.parse(JSON.stringify(copy));
let file = counters.localVar.counters.filesForUploadArr[i];
tempObj.fileInfo.ogname = file.name;
tempObj.fileInfo.meme = file.type;
tempObj.fileData = await readFile(file).then((file)=>{
file = btoa(file);
return file;
}).then((file)=>{
return file;
})
filesDataObj.push(tempObj);
}
return filesDataObj;
}
async function readFile (file){
const toBinaryString = file => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsBinaryString(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
let parsedFile = null;
parsedFile = await toBinaryString(file);
return parsedFile;
}
/*From doPost downward, we read the file Array convert the base64 to blob and make a file in google drive using the blob and metadata we have, you may also see some sheet code, I'm using sheet as db for this */
//in buit function doPost in Code.gs
doPost(e){
const myDataObj = JSON.parse(e.postData.contents);
mainFileFunc(myDataObj.params[0].dataObj.images);
//the actual object structure might look different from yours, console log around
}
function mainFileFunc(fileArr) {
let myArrObj = [{"madeit":"toFileF"}];
let copy = JSON.parse(JSON.stringify(myArrObj[0]));
//sheet.getRange("A1").setValue(JSON.stringify(fileArr.length));
for(let i=0 ; i < fileArr.length ; i++){
myArrObj.push(copy);
let blob = doFileStuff(fileArr[i].data,fileArr[i].info[0].mime,fileArr[i].id);
myArrObj[i] = uploadFileOne(blob,fileArr[i].id);
myArrObj[i].mime = fileArr[i].info[0].mime;
myArrObj[i].realName = fileArr[i].name;
// sheet.getRange("A"+(i+1)).setValue(myArrObj[i].name);
// sheet.getRange("B"+(i+1)).setValue(myArrObj[i].url);
// sheet.getRange("C"+(i+1)).setValue(myArrObj[i].mime);
// sheet.getRange("D"+(i+1)).setValue(myArrObj[i].size);
}
return myArrObj;
}
function doFileStuff(filedata,filetype,filename){
var data = Utilities.base64Decode(filedata, Utilities.Charset.UTF_8);
var blob = Utilities.newBlob(data,filetype,filename);
return blob;
}
function uploadFileOne(data,filename) {
let myObj = {}
myObj["name"] = "";
myObj["realName"] = "Story_Picture";
myObj["url"] = "";
myObj["mime"] = "";
myObj["size"] = "";
myObj["thumb"] = "nonety";
var folders = DriveApp.getFoldersByName("LadhaWeb");
while (folders.hasNext()) {
var folder = folders.next();
folder.createFile(data);
}
var files = DriveApp.getFilesByName(filename);
while (files.hasNext()) {
var file = files.next();
myObj.name = file.getName();
myObj.url = file.getUrl();
myObj.mime = file.getMimeType();
myObj.size = file.getSize();
}
return myObj;
}
You can view the full frontend code for this project here and the backend here.
Hope this helps someone.
I'm new to EPiSERVER. Currently trying to search for a page with a specific property set to a specific value.
I need the property CatalogEntryPoint (a ContentReference) to equal something. Here is the criterea:
PropertyCriteria secCriteria = new PropertyCriteria();
secCriteria.Condition = CompareCondition.Equal;
secCriteria.Name = "CatalogEntryPoint.ID";
secCriteria.Type = PropertyDataType.Number;
secCriteria.Value = currentContent.ContentLink.ID.ToString();
secCriteria.Required = true;
And here is an excerpt from the search index:
{
"CatalogEntryPoint": {
"$type": "EPiServer.Find.Cms.IndexableContentReference, EPiServer.Find.Cms",
"ID$$number": 1073742170,
"WorkID$$number": 0,
"ProviderName$$string": "CatalogContent",
"GetPublishedOrLatest$$bool": false,
"IsExternalProvider$$bool": true,
"___types": [
"EPiServer.Find.Cms.IndexableContentReference",
"EPiServer.Core.ContentReference",
"System.Object",
"System.IComparable",
"EPiServer.Data.Entity.IReadOnly"
]
},
It would seem that the CatalogEntryPoint.ID-notation does not work as I'm getting 0 results. How should I write it?
The PropertyDataType has a ContentReference option. The following should work:
PropertyCriteria secCriteria = new PropertyCriteria();
secCriteria.Condition = CompareCondition.Equal;
secCriteria.Name = "CatalogEntryPoint";
secCriteria.Type = PropertyDataType.ContentReference;
secCriteria.Value = currentContent.ContentLink.ToString();
secCriteria.Required = true;
You could also just do ContentLink.ID.ToString(), the code ContentLink.ToString() preserves the content version I believe.
I have cross posted on the Adobe Forums.
Writing my first lightroom plugin, I have created a minimal example which should set the photo width here and included below. However I can not get the image to be the 400 x 400 specified.
ExportFilterProvider400.lua:
local LrView = import 'LrView'
local bind = LrView.bind
--------------------------------------------------------------------------------
-- This function will create the section displayed on the export dialog
-- when this filter is added to the export session.
local function sectionForFilterInDialog( f, propertyTable )
return {
title = LOC "$$$/SDK/MetaExportFilter/SectionTitle=400x400 Filter",
}
end
--------------------------------------------------------------------------------
-- Example on updating export settings
local function updateExportSettings( exportSettings )
exportSettings.LR_size_maxHeight = 400
exportSettings.LR_size_maxWidth = 400
exportSettings.LR_size_doConstrain = true
end
--------------------------------------------------------------------------------
return {
sectionForFilterInDialog = sectionForFilterInDialog,
updateExportSettings = updateExportSettings , --Does this work
}
Info.lua:
return {
LrSdkVersion = 3.0,
LrSdkMinimumVersion = 1.3,
LrPluginName = "400x400 Export",
LrToolkitIdentifier = 'sample.export400x400',
LrExportFilterProvider = {
title = LOC "$$$/SDK/MetaExportFilter/Sample=400x400 Size", -- the string that appears in the export filter section of the export dialog in LR
file = 'ExportFilterProvider400.lua', -- name of the file containing the filter definition script
id = "metadata1", -- unique identifier for export filter
},
VERSION = { major=5, minor=0, revision=0, build=907681, },
}
Adobe Lightroom can load the plugin, and add it to the export session, but the updateExportSettings do not seem to take effect. Tested in Lightroom 5.3.
Rob Cole on the Adobe SDK forum has pointed out that updateExportSettings is used by 'Export Service providers' to preset export settings.
'Export Filter providers' should use renditionOptions as part of postProcessRenderedPhotos.
After some trial and error I have this minimal example,
Info.lua (no change):
return {
LrSdkVersion = 3.0,
LrSdkMinimumVersion = 1.3, -- minimum SDK version required by this plugin
LrPluginName = "400x400 Export",
LrToolkitIdentifier = 'sample.export400x400',
LrExportFilterProvider = {
title = LOC "$$$/SDK/MetaExportFilter/Sample=400x400 Size",
file = 'ExportFilterProvider400.lua',
id = "metadata1", -- unique identifier for export filter
},
VERSION = { major=5, minor=0, revision=0, build=907681, },
}
ExportFilterProvider400.lua:
local LrView = import 'LrView'
local bind = LrView.bind
local function sectionForFilterInDialog( f, propertyTable )
logger:info('Called sectionForFilterInDialog')
return {
title = LOC "$$$/SDK/MetaExportFilter/SectionTitle=400x400 Filter",
}
end
local function postProcessRenderedPhotos( functionContext, filterContext )
local renditionOptions = {
filterSettings = function( renditionToSatisfy, exportSettings )
exportSettings.LR_size_maxHeight = 400
exportSettings.LR_size_maxWidth = 400
exportSettings.LR_size_doConstrain = true
end
}
for sourceRendition, renditionToSatisfy in filterContext:renditions( renditionOptions ) do
-- Wait for the upstream task to finish its work on this photo.
local success, pathOrMessage = sourceRendition:waitForRender()
end
end
--------------------------------------------------------------------------------
return {
sectionForFilterInDialog = sectionForFilterInDialog,
postProcessRenderedPhotos = postProcessRenderedPhotos,
}