-
Notifications
You must be signed in to change notification settings - Fork 0
/
spreadsheetSync.gs
192 lines (174 loc) · 7.79 KB
/
spreadsheetSync.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/*
This script syncs data from many different spreadsheets into one, avoiding creating duplicates by matching rows from the source sheets to the destination sheet on email and phone.
*/
var today = new Date();
var dd = String(today.getDate()).padStart(2, '0');
var mm = String(today.getMonth() + 1).padStart(2, '0'); //January is 0!
var yyyy = today.getFullYear();
var todayDate = mm + '/' + dd + '/' + yyyy;
var destinationSheetUrl = '<URL HERE>';
var destinationWorksheetTitle = 'Main';
var configWorksheetTitle = 'Configuration';
var configWorksheet = SpreadsheetApp.openByUrl(destinationSheetUrl).getSheetByName(configWorksheetTitle);
var destinationWorksheet = SpreadsheetApp.openByUrl(destinationSheetUrl).getSheetByName(destinationWorksheetTitle);
function getSourceData(spreadSheetUrl, worksheetTitle) {
// Connect to sheet and get data
let worksheet = SpreadsheetApp.openByUrl(spreadSheetUrl).getSheetByName(worksheetTitle);
let sourceData = worksheet.getDataRange().getValues();
// Gets the first row of the spreadsheet. In other words, the column names
let headerRow = sourceData[0];
// Loop through the column names to find the index of columns involved in sync
var firstEmptyColFound = false;
for (column = 0; column < headerRow.length; column++){
let lowerColumn = String(headerRow[column]).toLowerCase();
if (lowerColumn.includes('email')){
var emailColIdx = column;
} else if (lowerColumn.includes('name') && lowerColumn.includes('first')){
var firstNameColIdx = column;
} else if (lowerColumn.includes('name') && lowerColumn.includes('last')){
var lastNameColIdx = column;
} else if (lowerColumn.includes('phone')){
var phoneColIdx = column;
} else if (lowerColumn.includes('synced date')){
var syncedColIdx = column;
}
};
// If there is no synced date column, create one
if (typeof syncedColIdx === "undefined"){
worksheet.insertColumnAfter(headerRow.length)
worksheet.getRange(1, headerRow.length + 1).setValue('synced date');
var syncedColIdx = headerRow.length + 1;
};
return {
data: sourceData.slice(1),
emailColIdx: emailColIdx,
firstNameColIdx: firstNameColIdx,
lastNameColIdx: lastNameColIdx,
phoneColIdx: phoneColIdx,
syncedColIdx: syncedColIdx
};
}
function getExistingData () {
// Connect to main/destination sheet
let existingData = destinationWorksheet.getDataRange().getValues();
let existingPhones = [];
let existingEmails = [];
for (let i = 2; i < existingData.length; i++) {
var row = existingData[i];
if (row[3] != ''){
let phonetest = row[3];
let phoneStripped = row[3].toString().replace(/\D/g, '').trim();
var phone = phoneStripped.slice(phoneStripped.length - 10, phoneStripped.length);
} else {var phone = 'No Phone'};
if (row[2] != ''){
var email = String(row[2]).toLowerCase();
} else {var email = 'No Email'};
existingPhones.push(phone);
existingEmails.push(email);
};
return {
phones: existingPhones,
emails: existingEmails,
data: existingData
};
}
function syncSheet(sourceSheet, sourceDataAll, existingData) {
let newRows = [];
var sourceData = sourceDataAll.data;
let existingEmails = existingData.emails;
let existingPhones = existingData.phones;
for (let i = 0; i < sourceData.length; i++){
var newPhone = false;
var newEmail = false;
var row = sourceData[i];
// This array will be turn into the row we insert into the main spreadsheet
var insertRow = [];
// If source sheet had first name column, add first name to insertRow
if (typeof sourceDataAll.firstNameColIdx != "undefined"){
insertRow.push(row[sourceDataAll.firstNameColIdx]);
} else {insertRow.push('')};
// If source sheet had last name column, add last name to insertRow
if (typeof sourceDataAll.lastNameColIdx != "undefined"){
insertRow.push(row[sourceDataAll.lastNameColIdx]);
} else {insertRow.push('')};
// If the row hasn't been synced yet, then sync it
if (row[sourceDataAll.syncedColIdx] === ''){
// Check if email should be synced
if (typeof sourceDataAll.emailColIdx != "undefined"){
var email = String(row[sourceDataAll.emailColIdx]).toLowerCase();
// If email has not been synced and isn't in the destination/main sheet yet
if(!existingEmails.includes(email)){
newEmail = true;
} else {var matchRow = existingEmails.indexOf(email)};
} else{var email = '';};
// Check if phone should be synced
if (typeof sourceDataAll.phoneColIdx != "undefined"){
// Clean up phone number
let phoneStripped = row[sourceDataAll.phoneColIdx].toString().replace(/\D/g, '').trim();
var phone = phoneStripped.slice(phoneStripped.length - 10, phoneStripped.length)
if(!existingPhones.includes(phone)){
newPhone = true;
} else {var matchRow = existingPhones.indexOf(phone)}
} else {var phone = '';};
// If both email and phone are new, add new row to the newRows array
if((newPhone === true || phone == '') && (newEmail === true || email == '')){
insertRow.push(email);
insertRow.push(phone);
newRows.push(insertRow);
// If only the email is new, then push that to the spreadsheet
} else if (newPhone === true && newEmail === false){
destinationWorksheet.getRange(matchRow + 2, 3).setValue(phone);
// If only the phone is new, then push that to the spreadsheet
} else if (newEmail === true && newPhone === false){
destinationWorksheet.getRange(matchRow + 2, 3).setValue(email);
};
// Update the synced column in the source sheet so we don't sync this row again
sourceSheet.getRange(i + 2, sourceDataAll.syncedColIdx + 1).setValue(todayDate);
}
};
// Send new rows to main spreadsheet
if (newRows.length > 0){
destinationWorksheet.getRange(existingData.data.length + 1, 1, newRows.length, 4).setValues(newRows)
}
}
function main(){
// Get config sheet
var configLastRow = configWorksheet.getLastRow();
var configData = configWorksheet.getSheetValues(3,1,configLastRow - 2, 3);
// Get the contact info that already exists in the main sheet
var existingData = getExistingData();
// Loop through sheets listed in config worksheet and sync them or log errors
for (i=0; i<configData.length; i++) {
var row = configData[i];
let errors = '';
var sourceSpreadsheet = SpreadsheetApp.openByUrl(row[0]);
if (sourceSpreadsheet === null) {
errors+='Issue opening spreadsheet - make sure it is shared with google account running the script and URL is copied correctly. ';
};
var sourceWorksheet = sourceSpreadsheet.getSheetByName(row[1]);
if (sourceWorksheet === null){
errors+='Issue accessing worksheet. Check that worksheet title is correctly copied in configuration sheet. ';
};
if (errors.length > 0){
configWorksheet.getRange(i+3, 3).setValue(errors);
continue;
};
// Get data from source sheet
let sourceData = getSourceData(row[0], row[1]);
SpreadsheetApp.flush();
// If any of the essential columns are missing from the source sheet, log error and move to next source sheet
if (typeof sourceData.emailColIdx === "undefined" && typeof sourceData.phoneColIdx=== "undefined"){
errors += 'No email or phone column, or columns are mislabeled. ';
};
if (typeof sourceData.firstNameColIdx === "undefined" && typeof sourceData.lastNameColIdx === "undefined"){
errors += 'No first name nor last name columns, or columns are mislabeled. ';
};
if (errors.length > 0){
configWorksheet.getRange(i+3, 3).setValue(errors);
continue;
};
// Sync source sheet to main sheet
syncSheet(sourceWorksheet, sourceData, existingData);
configWorksheet.getRange(i+3, 3).setValue('Last Synced ' + todayDate);
}
}