how do i get google sheet UI - google-sheets-api

I was able to get sheet data like this
to get this result I wrote this
public class CreateSheetServlet extends HttpServlet{
#Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/plain");`
Sheets service = GoogleAPITestServlet.getSheetService();
Spreadsheet sheet = new Spreadsheet();
sheet.setSpreadsheetId("testSheet");
SpreadsheetProperties props = new SpreadsheetProperties();
props.setTitle("샘플 시트");
props.setLocale("ko_KR");
sheet.setProperties(props);
OutputStream os = resp.getOutputStream();
service.spreadsheets().create(sheet).executeAndDownloadTo(os);
}
}
than,I really want know how I get sheet UI like this

If you simply want to display the sheet on an external website, you can embed your Google Sheet on a webpage.
Otherwise, if you're looking for some way to display and edit data from OUTSIDE Google Sheets, then you can't.
Unless you implement the entire spreadsheet webapp from scratch, your only option is to use Google's UI. You can, however, have a somewhat Google Sheets "instance" (on their servers too) if you have Google for Work.

Related

Extend Office JavaScript API with own Browser Control

I'm trying to write a VSTO-Add-In with a System.Windows.Forms.WebBrowser-Control enabling something similar to the Office-JS-Add-In model.
The WebBrowser-control would show some HTML/JS-Page and be able to call C#-functions in the VSTO-Add-In from JavaScript via window.external and the ObjectForScripting-property of the WebBrowser-object.
That is in JS the call would be
window.external.DoFancyStuffToMyDocument(withTheseParams)
while there had to be some
class MyFunctionProxy() {
public void DoFancyStuffToMyDocument(string theParam) {
//code here
}
}
in the C#-Code an this would be attached to the WebBrowser
myWebBrowser.ObjectForScripting = new MyFunctionProxy();
So far so good. Now comes the catch. I want my HTML/JS-Code be able to also utilize the office.js code and functions like
Word.run(function (context) {
var thisDocument = context.document;
var range = thisDocument.getSelection();
range.insertText('"Hitch your wagon to a star."\n', Word.InsertLocation.replace);
//...
}
Does anyone see a way of getting this to work?
My initial guess was that the OfficeJS-taskpane-add-ins in Word on-prem use some some similar methode as above with a class derived from WebBrowser and the appropriate ObjectForScripting. This would then suggest that there must be a (hopefully accessible) class which is assigned to the ObjectForScripting-property handling the function calls from office.js. Then I could proxy this ObjectForScripting-class and add my own functions like 'DoFancyStuffToMyDocument()'.

JSF2.0: Show certain pdf page on load

I'd like to open a PDF in a new Page from JSF2, and display a certain page in this pdf on load. I have a kind of TOC in my jsf page, and want to jump from there to the page in the PDF directly.
What I know (this is not, what I need, just an example of giving adobe reader and other pdf readers the page I want to jump to):
Something like this will open the page (chose something from the internet):
https://www.cdc.gov/diabetes/pdfs/data/statistics/national-diabetes-statistics-report.pdf#page=10
The #page=10 makes the pdf plugin of the browser display page 10.
Requirements for selecting the PDF:
PDF is dynamically downloaded from a webservice according to an ID that must only reside in the ManagedBeans, since it's secret, and should not be passed to others (like Session ID...) (below given anser by me passes the ID in the GET-Parameter, which should not be done)
PDF should not reside in the Filesystem, sinc I don't want the handling of temporary files (below given answer by me actually utilizes PDFs on FS, with stream only it does not work)
Now my real problem: I have to change the URL beeing displayed/used in JSF, but can't use the normal way with and includeViewParams, because this will insert a "?", and not a "#" in the URL.
Also, I have a backing bean, that gets the content of the PDF from a backend service, based on some other parameters I'm giving, so a solution with would be cool, but I'm aware that this is probably not possible...
Does anyone have an idea, how to solve this?
I didn't include any code, since it doesn't work anyways, and I probably need a completely new way to solve this anyways...
Turns out, Primefaces has this already implemented (although the implementation has it's restrictions):
<p:media player="pdf" value="#{viewerBean.media}" width="100%" height="100%">
<f:param name="#page" value="#{viewerBean.pageNumber}"/>
<f:param name="toolbar" value="1"/>
<!--<f:param name="search" value="#{viewerBean.queryText}"/>-->
</p:media>
https://www.primefaces.org/showcase/ui/multimedia/media.xhtml
Restriction: Can't read from a stream, at least not very stable. Save your energy, and write a stream to a temp file, and set this filename dynamically. Not sure, whether this is complete, but you should get the idea:
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
import java.io.*;
import javax.annotation.PostConstruct;
import java.nio.file.Files;
import java.nio.file.Paths;
#ManagedBean
#RequestScoped
public class ViewerBean implements Serializable {
#ManagedProperty(value = "#{param.page}")
private String pageNumber;
private File media;
#PostConstruct
public void init() {
try {
media = Files.createTempFile("car", ".pdf").toFile();
try (FileOutputStream outputStream = new FileOutputStream(media)) {
IOUtils.copy(getStreamedContent().getStream(), outputStream);
}
} catch (IOException e) {
LOGGER.error(e);
throw new RuntimeException("Error creating temp file", e);
}
}
public StreamedContent getMedia() {
try {
return new DefaultStreamedContent(new FileInputStream(media), "application/pdf");
} catch (FileNotFoundException e) {
String message = "Error reading file " + media.getAbsolutePath();
LOGGER.error(message, e);
throw new RuntimeException(message, e);
}
}
}
If the pagename is not needed, you could use this:
http://balusc.omnifaces.org/2006/05/pdf-handling.html
Maybe if you can utilize outputLink for this you'll be lucky, but I ran out of time to test this option.
Found the (THE) solution; above answher mentions , but this cannot cope with #ViewScope beans, and sends many requests to the underlying bean for reading only one InputStream. I found this not acceptable for load reasons.
So here we go:
Create JSF page with <f:event type="preRenderView" listener="#{documentDownloadBean.writeIntpuStreamToResponseOutputStream}"/>
Put neccessary data for dynamic retrieval of the PDF into flash scope
redirect to above JSF page like so: return "document_search/view_pdf.xhtml?faces-redirect=true#page=" + page;
#ManagedBean
#ViewScoped
public class DocumentDownloadBean implements Serializable {
#ManagedProperty(value = "#{documentSearchBean}")
private DocumentSearchBean documentSearchBean;
public String activeDocumentToFlashScope(String page) {
Document document = documentSearchBean.getSelectedDocument();
FacesContext.getCurrentInstance().getExternalContext().getFlash().put("document", document);
// everything preapared now, redirect to viewing JSF page, with page=xxx parameter in URL, which will be evaluated by adobe pdf reader (and other readers, too)
return "document_search/view_pdf.xhtml?faces-redirect=true#page=" + page;
}
public void download() {
Document document = (Document) FacesContext.getCurrentInstance().getExternalContext().getFlash().get("document");
InputStream inputStream = getInputstreamFromBackingWebserviceSomehow(document);
FacesUtils.writeToResponseStream(FacesContext.getCurrentInstance().getExternalContext(), inputStream, document.getFileName());
}
}
Calling JSF Page:
<p:commandLink id="outputText" action="#{documentDownloadBean.activeDocumentToFlashScope(selectedDocument, page)}"
target="_blank" ajax="false">
<h:outputText value="View PDF"/>
</p:commandLink>

PDF String Extract a checkbox being checked or not

We have a method to check if a checkbox in a PDF (No forms) is checked or not and it works great on one company's PDF. But on another, there is no way to tell if the checkbox is checked or not.
Here is the code that works on one company's PDF
protected static final String[] HOLLOW_CHECKBOX = {"\uF06F", "\u0086"};
protected static final String[] FILLED_CHECKBOX = {"\uF06E", "\u0084"};
protected boolean isBoxChecked(String boxLabel, String content) {
content = content.trim();
for (String checkCharacter : FILLED_CHECKBOX) {
String option = String.format("%s %s", checkCharacter, boxLabel);
String option2 = String.format("%s%s", checkCharacter, boxLabel);
if (content.contains(option) || content.contains("\u0084 ") || content.contains(option2)) {
return true;
}
}
return false;
}
However, when I do the same for another company's PDF there is nothing in the extracted text near the checkbox to tell us if it is checked or not.
The big issue is we have no XML Schema, no Metadata, and no forms on these PDFs, it is just raw String, so you can see a checkbox is difficult to have in a String, but that is all we have. Here is code example of pulling the String in the PDF from a page to some other page, all the text in between
protected String getTextFromPages(int startPage, int endPage, PDDocument document) throws IOException {
PDFTextStripper stripper = new PDFTextStripper();
stripper.setStartPage(startPage);
stripper.setEndPage(endPage);
return stripper.getText(document);
}
I wish the pdfs had an easier way to extract the text/data, but these vendors that make the PDFs decided it was better to keep that out of them.
No we cannot have the vendor's/ other companies change anything, we receive these PDFs from the courts system that have been submitted by lawyers that we don't know and that the lawyers bought the PDF software that generates these files.
We also cannot do it the even longer way of trying to figure out the object model that PDFBox creates of the document with things like
o.apache.pdfbox.util.PDFStreamEngine - processing substream token: PDFOperator{Tf}
because these are 80-100 page PDFs and would take us years just to code to parse one vendor's format.

Google Sheets API v4 receives HTTP 401 responses for public feeds

I'm having no luck getting a response from v4 of the Google Sheets API when running against a public (i.e. "Published To The Web" AND shared with "Anyone On The Web") spreadsheet.
The relevant documentation states:
"If the request doesn't require authorization (such as a request for public data), then the application must provide either the API key or an OAuth 2.0 token, or both—whatever option is most convenient for you."
And to provide the API key, the documentation states:
"After you have an API key, your application can append the query parameter key=yourAPIKey to all request URLs."
So, I should be able to get a response listing the sheets in a public spreadsheet at the following URL:
https://sheets.googleapis.com/v4/spreadsheets/{spreadsheetId}?key={myAPIkey}
(with, obviously, the id and key supplied in the path and query string respectively)
However, when I do this, I get an HTTP 401 response:
{
error: {
code: 401,
message: "The request does not have valid authentication credentials.",
status: "UNAUTHENTICATED"
}
}
Can anyone else get this to work against a public workbook? If not, can anyone monitoring this thread from the Google side either comment or provide a working sample?
I managed to get this working. Even I was frustrated at first. And, this is not a bug. Here's how I did it:
First, enable these in your GDC to get rid of authentication errors.
-Google Apps Script Execution API
-Google Sheets API
Note: Make sure the Google account you used in GDC must be the same account you're using in Spreadsheet project else you might get a "The API Key and the authentication credential are from different projects" error message.
Go to https://developers.google.com/oauthplayground where you will acquire authorization tokens.
On Step 1, choose Google Sheets API v4 and choose https://www.googleapis.com/auth/spreadsheets scope so you have bot read and write permissions.
Click the Authorize APIs button. Allow the authentication and you'll proceed to Step 2.
On Step 2, click Exchange authorization code for tokens button. After that, proceed to Step 3.
On Step 3, time to paste your URL request. Since default server method is GET proceed and click Send the request button.
Note: Make sure your URL requests are the ones indicated in the Spreadsheetv4 docs.
Here's my sample URL request:
https://sheets.googleapis.com/v4/spreadsheets/SPREADSHEET_ID?includeGridData=false
I got a HTTP/1.1 200 OK and it displayed my requested data. This goes for all Spreadsheetv4 server-side processes.
Hope this helps.
We recently fixed this and it should now be working. Sorry for the troubles, please try again.
The document must be shared to "Anyone with the link" or "Public on the web". (Note: the publishing settings from "File -> Publish to the web" are irrelevant, unlike in the v3 API.)
This is not a solution of the problem but I think this is a good way to achieve the goal. On site http://embedded-lab.com/blog/post-data-google-sheets-using-esp8266/ I found how to update spreadsheet using Google Apps Script. This is an example with GET method. I will try to show you POST method with JSON format.
How to POST:
Create Google Spreadsheet, in the tab Tools > Script Editor paste following script. Modify the script by entering the appropriate spreadsheet ID and Sheet tab name (Line 27 and 28 in the script).
function doPost(e)
{
var success = false;
if (e != null)
{
var JSON_RawContent = e.postData.contents;
var PersonalData = JSON.parse(JSON_RawContent);
success = SaveData(
PersonalData.Name,
PersonalData.Age,
PersonalData.Phone
);
}
// Return plain text Output
return ContentService.createTextOutput("Data saved: " + success);
}
function SaveData(Name, Age, Phone)
{
try
{
var dateTime = new Date();
// Paste the URL of the Google Sheets starting from https thru /edit
// For e.g.: https://docs.google.com/---YOUR SPREADSHEET ID---/edit
var MyPersonalMatrix = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/---YOUR SPREADSHEET ID---/edit");
var MyBasicPersonalData = MyPersonalMatrix.getSheetByName("BasicPersonalData");
// Get last edited row
var row = MyBasicPersonalData.getLastRow() + 1;
MyBasicPersonalData.getRange("A" + row).setValue(Name);
MyBasicPersonalData.getRange("B" + row).setValue(Age);
MyBasicPersonalData.getRange("C" + row).setValue(Phone);
return true;
}
catch(error)
{
return false;
}
}
Now save the script and go to tab Publish > Deploy as Web App.
Execute the app as: Me xyz#gmail.com,
Who has access to the app: Anyone, even anonymous
Then to test you can use Postman app.
Or using UWP:
private async void Button_Click(object sender, RoutedEventArgs e)
{
using (HttpClient httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(#"https://script.google.com/");
httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("utf-8"));
string endpoint = #"/macros/s/---YOUR SCRIPT ID---/exec";
try
{
PersonalData personalData = new PersonalData();
personalData.Name = "Jarek";
personalData.Age = "34";
personalData.Phone = "111 222 333";
HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(personalData), Encoding.UTF8, "application/json");
HttpResponseMessage httpResponseMessage = await httpClient.PostAsync(endpoint, httpContent);
if (httpResponseMessage.IsSuccessStatusCode)
{
string jsonResponse = await httpResponseMessage.Content.ReadAsStringAsync();
//do something with json response here
}
}
catch (Exception ex)
{
}
}
}
public class PersonalData
{
public string Name;
public string Age;
public string Phone;
}
To above code NuGet Newtonsoft.Json is required.
Result:
If your feed is public and you are using api key, make sure you are throwing a http GET request.In case of POST request, you will receive this error.
I faced same.
Getting data using
Method: spreadsheets.getByDataFilter has POST request

Does WP7 save variables on close?

When my app closes will the values i have set still be there when I re open it?
Or is there a way to save them somewhere?
No they won't,
When you jump-out from the application, application will go to a state called TombStoned, it is your responsibility to store and retrieve useful page elements.
In order to do this, you need to store information on the following event on your page:
public override void OnNavigatedFrom(...)
{
State["XXX"] = txtName.Text; // save your data on page state (keep it low in size!)
}
the same way you need to retrieve your data on the following event
public override void OnNavigatedTo(...)
{
txtName.Text = State["XXX"]; // read your data from page state
// also check if state has any entry with this key
}
If you need to store application level data, you need to do it in your App.xaml.cs in the following events:
public override void OnDeactivated(...)
{
// Store in IsolatedStorageSettings
}
public override void OnActivated(...)
{
// Read from IsolatedStorageSettings
}
For more details about Tombstoning read the following article:
http://www.scottlogic.co.uk/blog/colin/2011/05/a-simple-windows-phone-7-mvvm-tombstoning-example/
When you app closes, all data information is lost unless you save it somewhere. For transient data, like page state things (e.g. textboxes, checkbox etc..), you can use PhoneApplicationPage.State. If you need to store data permanently so that it's there the next time the user launches the app, you should store it in Isolated Storage. You can learn more about tombstoning and when you should store states in this MSDN page.
There is also a helper library on CodePlex called Tombstone Helper which will make it easier to store data during tombstoning.