I have a Google App Script which generates XML from Google Sheet data. Each row of the sheet is an Athlete. In the XML file, I want to insert a static (i.e. not connected to a Sheet) set of nodes at the beginning.
Example:
<MEET>
<CLASSES>
<CLASS>
<NAME>Track</NAME>
</CLASS>
<CLASS>
<NAME>Field</NAME>
</CLASS>
</CLASSES>
<EVENTS>
<EVENT>
<NAME>Run</NAME>
</EVENT>
<EVENT>
<NAME>Throw</NAME>
</EVENT>
<EVENT>
<NAME>Jump</NAME>
</EVENT>
</EVENTS>
<ATHLETES>
<ATHLETE>
<NAME>Joe Smith</NAME>
<ADDRESS>123 Main St, Anytown, NY 12121</ADDRESS>
<EMAIL>joe#smith.com</EMAIL>
<PHONE>518-555-1234</PHONE>
<EMERGENCYNAME>Jane Smith</EMERGENCYNAME>
<EMERGENCYPHONE>518-555-5678</EMERGENCYPHONE>
<CLASS>Track</CLASS>
</ATHLETE>
</ATHLETES>
</MEET>
In this example, the root node is MEET and has numerous ATHLETE nodes added to it, based on the rows of the Google Sheet. However, the CLASSES and EVENTS will never change. I do want to be able to access them in the data though.
How do I insert these nodes before my dynamic content, within the root node?
Created a new Google Sheet for those elements, pulled them in same way as others.
Related
I am trying to set up Invantive Data Hub with Replicator. The default discovery creates entries for Exact Online and others, but there is no entry in settings.xml which shows me how to configure data cache.
This one exists for example:
<connection name="Exact Online (nl)" id="c149becf-01d3-4a58-9ee7-7369f34bdff5" description="{res:itgen_demo_exact_online_combined_nl}" sortingOrder="1000" authentication="Application" userLogonCodeMode="Auto" passwordMode="Auto" createdBy="jbu" createdOn="WS102" creationDate="2017-08-17T13:53:23.9351965+02:00">
<database order="0" createdBy="jbu" createdOn="WS102" creationDate="2017-08-17T13:53:23.9071956+02:00" provider="ExactOnlineAll" connectionString="apiUrl=https://start.exactonline.nl" />
</connection>
The console app has no editor for the settings.xml, so it must be done manually.
How can I configure the Replicator connection string to be used?
Using Google with different keywords, I've found a working setup. First Add a file settings-something.xml in the %USERPROFILE%\invantive.
The give it contents like below:
<?xml version="1.0" encoding="utf-16"?>
<settings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3" forcedefault="false">
<group name="Jurriaan" >
<connection name="Exact Online with PostgreSQL Data Cache" dataCacheConnectionString="provider=PostgreSql;connectionString={Server=dbserver;Database=db;User Id=db_owner;Password=db_pwd}" >
<database provider="ExactOnlineAll" connectionString="apiUrl=https://start.exactonline.nl" />
</connection>
</group>
</settings>
It would be handy when there would be a connection editor on Data Hub or at least a sample :-)
► Problem: Anyone can access a webpage, but I only want logged in users to be authorized to access it.
Background:
Web Server = IIS 8
Server OS = Windows Server 2012
Framework = .NET 4.5
Environment = .\WebFolder\logon.aspx, .\WebFolder\inside.html
Website = Simple logon page ("logon.aspx") that guards an html page ("inside.html").
Users = External people (ie, non-intranet)
Sample URLs:
A. "www.webpage.com/logon.aspx"
B. "www.webpage.com/inside.html"
Desired Outcome:
Everyone can access the "logon.aspx" page
Only logged on users can access the "inside.html" page
Any direct attempts to access "B" will trigger a redirect to "A"
No additional use of program code
Prior Attempts:
I've been fiddling with the web.config file (authentication & authorization), but to no avail (501 Server Error, 401 Authorization Error, Runtime Application Error).
Web.Config File:
<system.web>
<authentication>
<forms name=".ASPXFORMSAUTH" loginUrl="logon.aspx" protection="All" timeout="1" path="/" slidingExpiration="true" requireSSL="false" />
</authentication>
<authorization></authorization>
</system.web>
Bottom line: I'm sure this is a very basic/easy thing to configure, it's just that I haven't been able to do it so far. Plus, I do not want to write any additional code in order to accomplish a seemingly fundamental task.
Thanks in advance!
Okay, I figured it out (after 7 hours). It requires four things (based on the example file structure):
1. Using the FormsAuthentication module
VS2012 → Project → Your credentials/authentication code → Use FormsAuthentication.RedirectFromLogin(_var1_, _var2_) instead of Response.Redirect(inside.html)
2. Adding a new node in the web.config file
<system.webServer><handlers><add name="HTMLHandler" type="System.Web.StaticFileHandler" path="*.html" verb="GET" /></handlers>
3. Including the 'defaultUrl' attribute in the Forms tag
<forms name=".ASPXFORMSAUTH" loginUrl="logon.aspx" defaultUrl="inside.html" protection="All" timeout="1" path="/" slidingExpiration="false" requireSSL="false" />
4. Adding a location tag authorization restriction to the 'web.config' file
<location path="inside.html"><system.web><authorization><deny users="?" /></authorization></system.web></location>
See my comments (below) for an explanation of each of these four pieces.
I am currently working on a project where the system, which is a node.js web server subscribes to push notification for changes in the resource calendars of an Exchange server. We followed the MSDN documentation to subscribe and communicate with the Exchange server using SOAP requests.
We used SOAP request below to fetch the changes and store them in the local database of the web server. The '+roomCalId' and '+syncState+' values are replaced with room calendar Id and its corresponding sync state which are stored previously in the database when subscribing.
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<soap:Header>
<t:RequestServerVersion Version="Exchange2013"></t:RequestServerVersion>
<t:TimeZoneContext>
<t:TimeZoneDefinition Name="UTC" Id="UTC"></t:TimeZoneDefinition>
</t:TimeZoneContext>
<t:ExchangeImpersonation>
<t:ConnectingSID>
<t:PrimarySmtpAddress>+roomCalId+</t:PrimarySmtpAddress>
</t:ConnectingSID>
</t:ExchangeImpersonation>
</soap:Header>
<soap:Body>
<m:SyncFolderItems>
<m:ItemShape>
<t:BaseShape>AllProperties</t:BaseShape>
</m:ItemShape>
<m:SyncFolderId>
<t:DistinguishedFolderId Id="calendar" />
</m:SyncFolderId>
<m:SyncState>+syncState+</m:SyncState>
<m:MaxChangesReturned>500</m:MaxChangesReturned>
<m:SyncScope>NormalItems</m:SyncScope>
</m:SyncFolderItems>
</soap:Body>
</soap:Envelope>
The process worked perfectly without any problems for the first few calendars. However, for newly created room calendars, the soap request above returns the organizer's name as appointment title instead of the actual title. Is there a reason why this might be happening?
Thats is a default setting on Room mailboxes where the Organiser name is used to replace the Subject of a Meeting. This is done for security reasons as most people have access to Meeting rooms but generally people like HR might not want people to see the subject of the meeting (eg meeting to talk about downsizing etc). You can change this setting using the Set-CalendarProcessing cmdlet https://technet.microsoft.com/en-us/library/dd335046(v=exchg.160).aspx and the AddOrganizerToSubject parameter
I want to implement a workflow where users submit data via a Google Form, and their responses are automatically posted to a pre-existing PDF form.
I have a couple of PDF forms that I use frequently. I have created a Google Form to gather all of the information necessary to complete the PDF. Now I am trying to find a way to map the answers to the original PDF.
How can I accomplish that?
There is an article on patentbytes.com, Automatically Completing Your PDF Forms, which goes into some detail about this topic, and which is the inspiration for this answer.
With Google Apps Script, you cannot modify existing PDF forms. However, you can leverage the existing Import capabilities in applications such as Adobe Acrobat and Acrobat Reader, by scripting the generation of form data in a way that is easily imported.
Here's the idea:
Have users fill out Google Form. Use the form settings to ensure required questions are answered.
On form submission, have a spreadsheet-contained trigger function generate an XML file with the user's answers. It's simple to use text-substitution to complete this, but we'll use an alternative approach using Google's XmlService.
Transmit the XML-formatted answers to the administrator. This may be done via email, or by placing a file in Google Drive.
Use Adobe Acrobat or Reader to import the XML file into the pdf form. (If needed.)
Before proceeding, your PDF form needs to have specific characteristics:
It must be a fillable form.
It must include support for Export and Import of form data. (In Adobe Reader, you will see an "Extended" menu, as in this screen shot.)
We'll use the example form from the previously mentioned article as an example. It works, although it needs cleaning up.
Export a sample of XML form data
Using Acrobat Reader (or similar), fill out a sample form completely, and Export the form data as XML. (It simplifies future steps if you fill the form out using camelCase terms that will be used for the HTML template - for example inventionTitle.)
Create HTML template from exported XML
In the Apps Script editor, use File-New to create a new html file in the project, and name it "formXml". Paste the text content of the exported xml file into formXml.html.
The XML declaration needs to be in our final output, but will cause the HtmlService to crash if left in the template. Remove it from the template; we'll add it back in our code.
<?xml version="1.0" encoding="UTF-8"?>
(Optional) Prettify the XML, to make it easier to avoid introducing errors. (freeformatter.com has a useful xml formatter. I found that a first pass with "compact mode" followed by a second pass at 2 spaces per indent produced good results.
(Optional) Reorder the fields logically.
For each input field, replace the example text with valid printing scriplets.
inventionTitle becomes <?= inventionTitle ?>
formXml.html
Here is what your form XML template should end up like. We have only 5 of the form fields represented in this example.
<fields xmlns:xfdf="http://ns.adobe.com/xfdf-transition/">
<TitleofInvention xfdf:original="Title of Invention"><?= inventionTitle ?></TitleofInvention>
<Inventorone xfdf:original="Inventor one"><?= inventor1name ?></Inventorone>
<Citizenof xfdf:original="Citizen of"><?= inventor1citizenship ?></Citizenof>
<Inventortwo xfdf:original="Inventor two"><?= inventor2name ?></Inventortwo>
<Citizenof_2 xfdf:original="Citizen of_2"><?= inventor2citizenship ?></Citizenof_2>
</fields>
Code.gs
Here's the form submission trigger function. Each time a user fills out your on-line google form, this spreadsheet form submission trigger will process their responses, and save a timestamped xml file on your google drive, ready to be imported into a PDF form.
function formSubmission(eventData) {
// Get a handle on the xml template
var formXml = HtmlService.createTemplateFromFile('formXml');
// Replace templated values with user's input
formXml.inventionTitle = eventData.namedValues['Invention Title'];
formXml.inventor1name = eventData.namedValues['Inventor 1 Name'];
formXml.inventor1citizenship = eventData.namedValues['Inventor 1 Citizenship'];
formXml.inventor2name = eventData.namedValues['Inventor 2 Name'];
formXml.inventor2citizenship = eventData.namedValues['Inventor 2 Citizenship'];
// Evaluate the template with substitutions
var xml = formXml.evaluate();
// Get the evaluated template as text, prepend the XML Declaration
var formXmlText = '<?xml version="1.0" encoding="UTF-8"?>'
+ xml.getContent();
// Save user's input as an xml file on our Google Drive
var fileName = 'Form ' + eventData.namedValues['Timestamp'];
var xmlFile = DriveApp.createFile(fileName, formXmlText, MimeType.XML);
}
Form & Spreadsheet
The namedValues in the eventData object processed by the trigger function come from the Form Responses sheet, which are directly from the Form questions. (That's a good reason to keep the questions short, and rely on the Help Text to elaborate!)
I'm trying to update Jelly scripts in my Jenkins setup to email the reason for a build (the build trigger), but I can't find any documentation on this.
I know it should be available, as the build's page will show the information, but I want it to be displayed on the email being distributed.
Does anyone know if there is a var I can query, or a Jenkins API call I can call to get this?
You can do it by calling this API.
More convinient, in env var setted before the build, you'll find BUILD_URL :
BUILD_URL=https://jenkins-server.tld/job/JOBNAME/BUILD_NUMBER
So you just need to append /api/json. You can also got it in xml :
<freeStyleBuild>
<action>
<cause>
<shortDescription>Started by user kenji</shortDescription>
<userName>kenji</userName>
</cause>
</action>
<action/>
<action/>
<action>
<failCount>0</failCount>
<skipCount>0</skipCount>
<totalCount>1</totalCount>
<urlName>testReport</urlName>
</action>
<building>false</building>
<duration>9772</duration>
<fullDisplayName>JOBNAME #4</fullDisplayName>
<id>2011-08-10_11-19-42</id>
<keepLog>false</keepLog>
<number>4</number>
<result>SUCCESS</result>
<timestamp>1312967982296</timestamp>
<url>https://jenkins-server.tld/job/JOBNAME/4/</url>
<builtOn>macboo</builtOn>
<changeSet>
<kind>svn</kind>
<revision>
<module>https://svn-server.tld/JOBNAME/trunk</module>
<revision>7</revision>
</revision>
</changeSet>
</freeStyleBuild>