Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

Help - Google Sheets and App Script integration (Delphi 7, Indy 10 - "404 Error - Not Found")

Hi everyone,

I would be forever thankful if someone could help solving this issue, I'm trying to solve it for ten days now without success.

I'm working on a feature in my Delphi 7 application (using Indy 10) that needs to be integrated with Google Sheets and Google Scripts. In summary, I need to programmatically send a Google Sheets to my Google Drive and, in sequence, to create a App Script and bind it to my Google Sheets doc, because I need that my Google Sheets to perform the script.

My code is working regarding the following: (1) it is creating the Sheets in the desired google drive's folder; (2) It is creating the Script Project and (3) It is creating the Script Project as a contêiner-bounded script. When I access the Sheets through my browser, I can find the Project binded to the Sheets (opening the latter and acessing the App Script in Menu -> Extensions).

However, that said, my code is not working when I tried to add a File (.gs) to the Project, it is returning the following error: "HTTP/1.0 404 Not Found".

I already tried a lot of suggestions and already verified the Script-ID and a lot of other tries bue none of them seems to work. I don't if there is something wrong with the code, or if it is a matter of acesses and permissions...

Notes:

- Please consider that the variable that I named "IdDaPlanilha" is actually carrying the Script ID. I correct this during the programming but have not still altered the name of the variable.

- I'm using Postman to get the Access Token. The scope of the access token is configured as following:

https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/script.projects https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/script.deployments https://www.googleapis.com/auth/drive.file

- The Google API is activated in my google account, so is the configuration of the OAuth . 

Following I'm sharing the relevant portion of my code, especially the sections where I am:

- Generating the .gs file content.
- Making the API requests for creating the Apps Script project and associating it with the Google Sheets file.
- Configuring and sending HTTP requests using Indy 10.

Here it is:

function TCadCompras_Cotacoes.EnviarParaGoogleDrive( pAccessToken, pCaminho : string ; pPlanilha : ShortString ) : string;
var

HTTP: TIdHTTP;
SSL: TIdSSLIOHandlerSocketOpenSSL;
FormData: TIdMultiPartFormDataStream;
Response, MetadataStream: TStringStream;
JSONResponse: string;

FileContent: TMemoryStream;

FileURL: string;

Boundary, Body, Metadata : string;

vRes : string;

PermissionData: TStringStream;
PermissionPayload: string;
RespP : TStringStream;


vScriptCode : String ;

IdDaPlanilha : string ;

IdDaPasta : string ;


IdDoScript : string ;

begin


pAccessToken:= Trim( Observacao.text );

if 1=1 then
Begin

Result := '';
HTTP := TIdHTTP.Create(nil);
SSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
Response := TStringStream.Create('');
MetadataStream := TStringStream.Create('');
FileContent := TMemoryStream.Create;
try

// Loads the content from the Sheets to the FileContent
FileContent.LoadFromFile( pCaminho + pPlanilha );

// Defines the boundary to separate the parts of the request
Boundary := '-------314159265358979323846';

// Puts together the metadata JSON (name and mimeType of the file )

IdDaPasta := '1D8Iywwgzqyv1bIQ41owNzwaHb4YTTe67';

Metadata := '--' + Boundary + #13#10 +
'Content-Type: application/json; charset=UTF-8' + #13#10#13#10 +
'{"name": "' + pPlanilha + '", "parents": ["' + IdDaPasta + '"] , "mimeType": "application/vnd.google-apps.spreadsheet"}' + #13#10 +
'--' + Boundary + #13#10 +
'Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + #13#10#13#10;


// Adds the JSON metada in the MetadataStream
MetadataStream.WriteString(Metadata);
MetadataStream.Position := 0;

// Copies the MetadataStream to the Response
Response.CopyFrom(MetadataStream, MetadataStream.Size);

// Copies the sheets content to the  Response
FileContent.Position := 0;
Response.CopyFrom(FileContent, FileContent.Size);

// Adds the final portion of the boundary
Response.WriteString(#13#10 + '--' + Boundary + '--' + #13#10);

// Configures the HTTP

SSL.SSLOptions.SSLVersions := [sslvSSLv23];
HTTP.IOHandler := SSL;
HTTP.Request.ContentType := 'multipart/related; boundary="' + Boundary + '"';
HTTP.Request.CustomHeaders.AddValue('Authorization', 'Bearer ' + pAccessToken);

// Sends the request and captures the response 

vRes := HTTP.Post('https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart', Response);

 

IdDaPlanilha := JSON_Conteudo( vRes , 'id');

// Builds the URL of the file in Google Drive
if IdDaPlanilha <> '' then
Begin

IdDoScript := EnviarScript( pAccessToken , IdDaPlanilha );

 

vScriptCode :='function myFunction() { SpreadsheetApp.getUi().alert("Alo Mundo") }';


AddAppsScriptToGoogleSheet( vScriptCode, pAccessToken , IdDoScript ); // <<<---- Liberar aqui....


// Result := FileURL;

Result := IdDaPlanilha;
end
else
begin
ShowMessage('ID não encontrado na resposta JSON');
end;
finally
HTTP.Free;
SSL.Free;
Response.Free;
MetadataStream.Free;
FileContent.Free;
PermissionData.Free;
RespP.Free;

end;


end; // 1=2

end;

 

function TCadCompras_Cotacoes.EnviarScript( pAccessToken, pIdDaPlanilha : string ) : string;
var
IdHTTP: TIdHTTP;
RequestBody, Response: TStringStream;
vRes, URL, AccessToken, JSONPayload: string;

JSONBody22: TStringStream;
xxx2 : TStringStream;
xxx: string ;

IdDoScript : string ;

begin
IdHTTP := TIdHTTP.Create(nil);
try


// Configures the authentication header 
IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'Bearer ' + pAccessToken;
IdHTTP.Request.ContentType := 'application/json';

// URL of the API in Google Apps Script
URL := 'https://script.googleapis.com/v1/projects';

// Body of the request in JSON
JSONPayload := '{"title": "Meu Script OnEdit 12", "parentId": "' + pIdDaPlanilha + '"}';

// Creates the body of the request with UTF-8 manually
RequestBody := TStringStream.Create(UTF8Encode(JSONPayload)); // Codifica como UTF-8
Response := TStringStream.Create('');

try
// Send the POST request
IdHTTP.Post(URL, RequestBody, Response);
IdDoScript := JSON_Conteudo( Response.DataString , 'scriptId');


result := IdDoScript;

finally
RequestBody.Free;
Response.Free;
end;
except
on E: Exception do
ShowMessage('Erro: ' + E.Message);
end;
IdHTTP.Free;
end;

 

procedure TCadCompras_Cotacoes.AddAppsScriptToGoogleSheet(const ScriptCode, pAccessToken , pIdDaPlanilha: string);
var
HTTP: TIdHTTP;
SSL: TIdSSLIOHandlerSocketOpenSSL;
JSONBody, Response: string;
AccessToken: string;

 

qID : String ;
url : String ;
begin

HTTP := TIdHTTP.Create(nil);
SSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);

try
HTTP.IOHandler := SSL;
HTTP.Request.ContentType := 'application/json';
HTTP.Request.CustomHeaders.AddValue('Authorization', 'Bearer ' + pAccessToken);

// Creates the JSON to Apps Script
JSONBody := Format(
'{"files": [{"name": "CodeY1", "type": "SERVER_JS", "source": "%s"}]}',
[ScriptCode]
);

 

qid := pIdDaPlanilha;// 16/01 14:02 não deu resultado

// Sends the request to create the Apps Script
try

url := 'https://script.googleapis.com/v1/projects/'+qId+'/content';

Response := HTTP.Post( URL , TStringStream.Create(JSONBody));

except
on e:exception do
Showmessage('Erro.: '+e.message );
end;
finally
HTTP.Free;
SSL.Free;
end;
end;

 

 

0 0 113
0 REPLIES 0
Top Solution Authors