forked from liddiard/google-sheet-s3
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCode.gs
126 lines (114 loc) · 4.32 KB
/
Code.gs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
function createMenu() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Publish to S3')
.addItem('Configure...', 'showConfig')
.addToUi();
}
function onInstall() {
createMenu();
}
function onOpen() {
createMenu();
}
// publish updated JSON to S3 if changes were made to the first sheet
// event object passed if called from trigger
function publish(event) {
// do nothing if required configuration settings are not present
if (!hasRequiredProps()) {
return;
}
// do nothing if the edited sheet is not the first one
var sheet = SpreadsheetApp.getActiveSpreadsheet();
// sheets are indexed from 1 instead of 0
//if (sheet.getActiveSheet().getIndex() > 1) {
//return;
//}
// get cell values from the range that contains data (2D array)
var rows = sheet
.getDataRange()
.getValues();
// filter out empty rows
rows = rows.filter(function(row){
return row
.some(function(value){
return typeof value !== 'string' || value.length;
});
})
// filter out columns that don't have a header (i.e. text in row 1)
.map(function(row){
return row
.filter(function(value, index){
return rows[0][index].length;
});
});
// create an array of objects keyed by header
var objs = rows
.slice(1)
.map(function(row){
var obj = {};
row.forEach(function(value, index){
var prop = rows[0][index];
// represent blank cell values as `null`
// blank cells always appear as an empty string regardless of the data
// type of other values in the column. neutralizing everything to `null`
// lets us avoid mixing empty strings with other data types for a prop.
obj[prop] = (typeof value === 'string' && !value.length) ? null : value;
});
return obj;
});
objs = objs.map(function(item){ return JSON.stringify(item) }).join('\n')
// upload to S3`
// https://engetc.com/projects/amazon-s3-api-binding-for-google-apps-script/
var props = PropertiesService.getDocumentProperties().getProperties();
var s3 = S3.getInstance(props.awsAccessKeyId, props.awsSecretKey);
s3.putObject(props.bucketName, [props.path, sheet.getActiveSheet().getName().replace(" ","_")+".jsonl"].join('/'), objs);
}
// show the configuration modal dialog UI
function showConfig() {
var sheet = SpreadsheetApp.getActiveSheet();
var ui = SpreadsheetApp.getUi();
var props = PropertiesService.getDocumentProperties().getProperties();
var template = HtmlService.createTemplateFromFile('config');
template.sheetName = sheet.getName()+".jsonl";
template.bucketName = props.bucketName || '';
template.path = props.path || '';
template.awsAccessKeyId = props.awsAccessKeyId || '';
template.awsSecretKey = props.awsSecretKey || '';
ui.showModalDialog(template.evaluate(), 'Amazon S3 publish configuration');
}
// update document configuration with values from form UI
function updateConfig(form) {
//var sheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
PropertiesService.getDocumentProperties().setProperties({
bucketName: form.bucketName,
path: form.path,
awsAccessKeyId: form.awsAccessKeyId,
awsSecretKey: form.awsSecretKey,
});
var message;
if (hasRequiredProps()) {
message = 'Published spreadsheet will be accessible at: \nhttps://' + form.bucketName + '.s3.amazonaws.com/' + form.path + '/' + sheet.getName();
publish();
// Create an onChange trigger programatically instead of manually because
// manual triggers disappear for no reason. See:
// https://code.google.com/p/google-apps-script-issues/issues/detail?id=4854
// https://code.google.com/p/google-apps-script-issues/issues/detail?id=5831
var sheet = SpreadsheetApp.getActive();
ScriptApp.newTrigger("publish")
.forSpreadsheet(sheet)
.onChange()
.create();
}
else {
message = 'You will need to fill out all configuration options for your spreadsheet to be published to S3.';
}
var ui = SpreadsheetApp.getUi();
ui.alert('✓ Configuration updated', message, ui.ButtonSet.OK);
}
// checks if document has the required configuration settings to publish to S3
// does not check if the config is valid
function hasRequiredProps() {
var props = PropertiesService.getDocumentProperties().getProperties();
return props.bucketName && props.awsAccessKeyId && props.awsSecretKey;
}