Post

Slack Creates an Automated WFH Employee Health Reporting System

Enhancing work efficiency with Slack Workflow combined with Google Sheets and App Script

Slack Creates an Automated WFH Employee Health Reporting System

ā„¹ļøā„¹ļøā„¹ļø The following content is translated by OpenAI.

Click here to view the original Chinese version. | é»žę­¤ęŸ„ēœ‹ęœ¬ę–‡äø­ę–‡ē‰ˆ


Slack Creates an Automated WFH Employee Health Reporting System

Enhancing work efficiency with Slack Workflow combined with Google Sheets and App Script

Photo by [Stephen Phillips ā€” Hostreviews.co.uk](https://unsplash.com/@hostreviews?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText){:target="_blank"}

Photo by Stephen Phillips ā€” Hostreviews.co.uk

Introduction

In response to the shift to remote work, the company is concerned about the health of all members, requiring daily reports on their health status, which are centrally recorded and managed by People Operations.

Our Flow Before Optimization

  1. [Automation] A Slack Channel sends a daily reminder message about the health form at 10 AM (the only automated part before optimization).
  2. Employees click the link to open the Google Form and fill out health questions.
  3. Data is stored back in Google Sheets for response records.
  4. [Manual] People Operations compares the list daily near the end of the workday to identify employees who forgot to fill out the form.
  5. [Manual] A reminder message is sent in the Slack Channel, tagging each employee who forgot to fill it out.

The above is our companyā€™s health reporting tracking process. Each company will have different processes based on its size and operational methods. This article serves only as an optimization example to learn about Slack Workflow usage and basic App Script writing; actual implementation should be done on a case-by-case basis.

Issues

  • Employees need to leave the Slack context to open the Google Form in a browser, which is especially inconvenient on mobile devices.
  • Google Form can only automatically include email information, and cannot automatically add the respondentā€™s name or department information.
  • Daily manual comparisons and tagging consume a lot of manpower and time.

Solution

Having done quite a few automation projects, I found this process suitable for automation due to its fixed data source (employee list), simple conditions, and routine actions. Initially, I didnā€™t implement it because I couldnā€™t find a good way to fill it out (actually, I couldnā€™t find an interesting point to study). I left it aside until I saw this post by Hai Zongli, which made me realize that Slack Workflow can do more than just send scheduled messages; it also has form capabilities:

Image from: [Hai Zongli](https://www.facebook.com/tzangms/posts/10157880898787657){:target="_blank"}

Image from: Hai Zongli

Now I was eager to get started!

If I could combine Slack Workflow Forms with automated messaging, wouldnā€™t that solve all the pain points mentioned above? The principle seemed feasible! So I began to implement it.

Flow After Optimization

First, hereā€™s the optimized flow and results.

  1. [Automation] A Slack Channel sends a daily reminder message about the health form at 10 AM.
  2. Employees fill out health questions via Google Form or Slack Workflow Form.
  3. Data is stored back in Google Sheets for response records.
  4. People Operations clicks the ā€œGenerate Unfilled Listā€ button daily near the end of the workday.
  5. [Automation] App Script compares the employee list with the filled-out list to identify those who havenā€™t filled it out.
  6. [Automation] Clicking ā€œGenerate & Send Messageā€ automatically sends reminders to those who havenā€™t filled it out and tags them.
  7. Done!

Results

(Personal estimate)

  • Each employee can reduce their filling time by about 30 seconds daily.
  • People Operations can save about 20 to 30 minutes daily on this task.

Operational Principles

Using App Script to manage the Sheet:

  1. Store all externally input data in the Responses Sheet.
  2. Write an App Script function to distribute the Responses data into sheets by fill date; if a date sheet does not exist, create a new one, naming it directly by date for easy identification.
  3. Compare the current dateā€™s sheet with the employee list to generate the unfilled list sheetā€™s data.
  4. Read the unfilled list sheet to compose messages and send them to the designated Slack Channel.
  • Integrating the Slack APP API allows automatic reading of the specified channel to import the employee list.
  • Message content uses the Slack UID Tag <@UID> to tag unfilled members.

Identity Verification

The identity verification information connecting Google Form and Slack is the email, so please ensure that all company colleagues use their company email to fill out the Google Form, and that their Slack personal information also includes their company email.

Getting Started

After discussing the issues, optimization methods, and results, we now move on to the implementation phase; letā€™s complete this automation case step by step together.

The article is a bit lengthy; feel free to skip sections you already understand, or directly create a copy from the completed result to learn while modifying.

Completed result form: https://forms.gle/aqGDCELpAiMFFoyDA

Completed result Google Sheet:

Steps are omitted; if you have questions, please Google it. Here, I assume you have already created and linked the health reporting form.

Remember to check ā€œCollect emailsā€ in the form:

This collects the email of the respondent for later comparison.

How to link responses to Google Sheets?

Switch to ā€œResponsesā€ at the top of the form and click the ā€œGoogle Sheets Icon.ā€

Change the linked Sheet name:

It is recommended to change the linked Sheet name from Form Responses 1 to Responses for easier use.

Create a Slack Workflow Form Entry

After establishing the traditional Google Form entry, letā€™s add a Slack filling method.

In any Slack conversation window, find the ā€œblue lightning āš”ļøā€ below the input box and click it.

In the menu below ā€œSearch shortcuts,ā€ type ā€œworkflowā€ and select ā€œOpen Workflow Builder.ā€

This will list the workflows you have created or participated in. Click the ā€œCreateā€ button in the upper right corner to create a new workflow.

In the first step, enter the workflow name (for display in the Workflow Builder interface).

Select ā€œShortcutā€ as the workflow trigger.

Currently, there are five types of Slack workflow trigger points:

  • Shortcut: Manually triggered by the ā€œblue lightning āš”ļøā€ option, which will appear in the workflow menu, allowing you to start the workflow by clicking it.
  • New channel member: When a new member joins the target channelā€¦ (e.g., welcome message).
  • Emoji reactions: When someone reacts to a message in the target channel with a specified emojiā€¦ (perhaps to mark important messages as read).
  • Scheduled date & time: Scheduled to trigger at a specified timeā€¦ (e.g., to send a reminder message).
  • Webhook: External webhook triggers, an advanced feature that can connect with third-party or self-hosted APIs to integrate internal workflows.

Here, we choose ā€œShortcutā€ to create a manual trigger option.

Select which channel this workflow shortcut will be added under and enter the ā€œdisplay name.ā€

*A workflow shortcut can only be added to one channel.

The shortcut is created! Now, letā€™s start adding steps to the workflow by clicking ā€œAdd Step.ā€

Select the ā€œSend a formā€ step.

Title: Enter the form title.

Add a question: Enter the title of the first question (you can label the question number in the title, e.g., 1., 2., 3ā€¦).

Choose a question type:

  • Short answer: Single-line input box.
  • Long answer: Multi-line input box.
  • Select from a list: Single-choice list.
  • Select a person: Choose a member from the same workspace.
  • Select a channel or DM: Choose a member from the same workspace or a group DM or channel.

For example, with ā€œSelect from a listā€:

  1. Add list item: You can add an option.
  2. Default selection: Choose a default option.
  3. Make this required: Set this question as mandatory.

  1. Add Question: You can add more questions.
  2. The right-side ā€œā†“ā€ and ā€œā¬†ā€ can adjust the order, and ā€œāœŽā€ can expand for editing.
  3. You can choose whether to send the form responses back to the channel or to someone.

You can also choose to send responses toā€¦:

  • Person who clickedā€¦: The person who clicked this form (the same as the respondent).
  • Channel where workflow started: The channel to which this workflow was added.

After completing the form, click ā€œSaveā€ to save the step.

*Here, we uncheck the option to send form responses back because we want to customize the message content in later steps.

Connect Slack Workflow Form with Google Sheets

If you havenā€™t added the Google Sheets app to Slack yet, you can click here to install the app.

Continuing from the previous step, click ā€œAdd Stepā€ to add a new step, and select ā€œAdd a spreadsheet rowā€ from Google Sheets for Workflow Builder.

  1. First, complete the Google account authorization by clicking ā€œConnect account.ā€
  2. Select a spreadsheet: Choose the target Google Sheet for responses, which should be the Google Sheet linked to the Google Form you created earlier.
  3. Sheet: Same as above.
  4. Column name: The first column where you want to fill in values; here, select question one.

Click the lower right ā€œInsert Variableā€ to select ā€œResponse to question oneā€¦ā€ After inserting, you can use the left ā€œAdd Columnā€ to add other fields, and so on to complete questions two, three, etc.

For the respondentā€™s email, you can choose ā€œPerson who submitted form.ā€

Then click to insert the variable and select ā€œEmailā€ to automatically include the respondentā€™s email.

  • Mention (default): Tag that user, raw data is <@User ID>.
  • Name: User name.
  • Email: User email.

The Timestamp field is a bit tricky; I will provide additional setup methods later. For now, click ā€œSaveā€ to save and then click ā€œPublishā€ in the upper right corner to publish the shortcut.

After seeing the successful publication message, you can return to the Slack Channel to test it out.

At this point, clicking the lightning bolt will show the workflow form you just created, which you can click to fill out and test.

Left: Computer Right: Mobile Version

Left: Computer / Right: Mobile Version

We can fill in the information and click ā€œSubmitā€ to test if it works correctly.

Success! However, we can see that the Timestamp field is empty; letā€™s solve this problem next.

Obtaining the Fill Time from Slack Workflow Form

Currently, there is no global variable for the current timestamp available in Slack workflows, at least not yet. I only found a wish post on reddit.

Initially, I whimsically tried entering =NOW() in the Column Value, but this would make all records show the current time, which is completely incorrect.

Thanks to the clever method provided by a user in that reddit post, you can create a clean Timestamp Sheet with a row of data and a column set to =NOW(), forcing the column to update to the latest time when you use Update, allowing you to select and get the current timestamp.

As shown in the image, click here to view the example.

  • Row: Used similarly to an ID, simply set it to ā€œ1ā€; this will be needed for Select & Update later to indicate the data row.
  • Timestamp: Set the value to =NOW() to always display the current time.
  • Value: Used to trigger the Timestamp column to update the time; the content can be anything; here, I put the respondentā€™s email to trigger the update.

You can right-click on the Sheet and select ā€œHide Sheetā€ to hide this sheet since it is not meant for external use.

Now, return to the Slack Workflow Builder to edit the workflow form you just created.

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
Click "Add Step" to add a new step:

![](/assets/d61062833c1a/1*5lIcdnMQnmglNxaiY8fNUQ.png)

Scroll down and select "Update a spreadsheet row"

![](/assets/d61062833c1a/1*kRBL8iptGYd2Gsy7Lv6gGA.png)

In "Select a spreadsheet," choose the previously created Sheet, and in "Sheet," select the newly created "Timestamp" Sheet.

In "Choose a column to search," select "Row," and for "Define a cell value to find," enter "1."

![](/assets/d61062833c1a/1*H8pb9TKvazhqiKKSCKcwCQ.png)

In "Update these columns," select "Column name" as "Value," then click "Insert variable" -> "Person who submitted" -> "Select Email."

Click "Save" to finish! The timestamp update in the Sheet has been successfully triggered, and now it's time to read it out.

![](/assets/d61062833c1a/1*avXovKvXz9mlHOq2NWaf3A.png)

Return to the editing page and click "Add Step" again to add a new step. This time select "Select a spreadsheet row" to read the Timestamp.

![](/assets/d61062833c1a/1*xEbDUkWd3utQ9QpllqSNHg.png)

The Search section is the same as "Update a spreadsheet row," then click "Save."

![](/assets/d61062833c1a/1*VO3lfeTe1bxlL3xN3_wtwQ.png)

After saving, return to the step list page. You can drag and drop to change the order of the steps.

Change the order to "Update a spreadsheet row" -> "Select a spreadsheet" -> "Add a spreadsheet row."

This means: Update triggers the timestamp update -> Read the Timestamp -> Use it when adding a new Row.

In "Add a spreadsheet row," click "Edit":

![](/assets/d61062833c1a/1*8IH_AJZn0YHFk5obccmUYg.png)

Scroll to the bottom and click "Add Column" in the lower left corner, then click "Insert a variable" in the lower right corner, find the "Timestamp" variable in the "Select a spreadsheet" section, and inject it.

![](/assets/d61062833c1a/1*-4vk8fjRwkIVSY4Pu-C6VA.png)

After clicking "Save" to save the step, return to the list page and click "Publish Change" in the upper right corner to publish the changes.

Now let's test the workflow shortcut again to see if the timestamp is written correctly.

![](/assets/d61062833c1a/1*GyJ-55XxVEcZ6Cb1Q_H-WQ.png)

Success!
#### Adding a Response to Slack Workflow Form

Just like with Google Forms, you can also add a response to the Slack workflow form.

On the editing step page, we can add another step by clicking "Add Step."

![](/assets/d61062833c1a/1*16JMg7a_YzUHnnY6JtBrGw.png)

This time select "Send a message"

![](/assets/d61062833c1a/1*2CJuPDtuaTM9P5wIKwPspQ.png)

In "Send this message to," select "Person who submitted form"

![](/assets/d61062833c1a/1*xKh_l7A-z31B6rQPboFTAA.png)

For the message content, sequentially enter the question title, then click "Insert a variable" to select "Response to Question XXX," and you can also insert "Timestamp" at the end. Click "Save" to save the step, then click "Publish Changes"!

> _You can also use "Send a message" to send the response results to a specific Channel or DM._

![](/assets/d61062833c1a/1*gfTjTnaNmu-aPj0MuF6M_Q.png)

Success!

The setup for the Slack workflow form is mostly complete; feel free to mix and match other functionalities.
### Google Sheet with App Script!

Next, we need to write an App Script to handle the submitted data.

![](/assets/d61062833c1a/1*04KBQF7e4lCjQm5XeHgVrA.png)

First, in the Google Sheet toolbar, select "Tools" -> "Script editor"

![](/assets/d61062833c1a/1*wlg8D_1DHONj__M1dSBCxw.png)

You can click the upper left corner to give the project a name.

Now we can start writing the App Script! App Script is designed based on JavaScript, so you can directly use JavaScript code along with Google Sheet's library.
#### Distributing Responses Data to Each Date's Sheet According to Submission Date

![](/assets/d61062833c1a/1*T5ExI_5aSf7QY5Zj_gJ3eg.png)

```javascript
function formatData() {
  var bufferSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Responses') // Name of the sheet storing responses
  
  var rows = bufferSheet.getDataRange().getValues();
  var fields = [];
  var startDeleteIndex = -1;
  var deleteLength = 0;
  for(index in rows) {
    if (index == 0) {
      fields = rows[index];
      continue;
    }

    var sheetName = rows[index][0].toLocaleDateString("en-US"); // Convert Date to String using US date format MM/DD/YYYY
    var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName); // Get MM/DD/YYYY Sheet
    if (sheet == null) { // If not, create a new one
      sheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet(sheetName, bufferSheet.getIndex());
      sheet.appendRow(fields);
    }

    sheet.appendRow(rows[index]); // Add data to the date Sheet
    if (startDeleteIndex == -1) {
      startDeleteIndex = +index + 1;
    }
    deleteLength += 1;
  }

  if (deleteLength > 0) {
    bufferSheet.deleteRows(startDeleteIndex, deleteLength); // After moving to the specified Sheet, remove data from Responses
  }
}

Paste the above code into the Code section and press ā€œcontrolā€ + ā€œsā€ to save.

Next, we need to add a trigger button in the Sheet ( it can only be triggered manually, it cannot be automatically triggered when data is written )

  1. First, create a new Sheet named ā€œUnfilled Listā€
  2. In the upper toolbar, select ā€œInsertā€ -> ā€œDrawingā€

Using this interface, draw a button.

After clicking ā€œSave and Close,ā€ you can adjust and move the button; click the upper right corner ā€œā€¦ā€ and select ā€œAssign scriptā€

Enter the function name ā€œformatData.ā€

You can click the added button to test its functionality

If ā€œAuthorization Requiredā€ appears, click ā€œContinueā€ to complete the verification

During the authentication process, ā€œGoogle hasnā€™t verified this appā€ will appear, which is normal since the App Script we wrote has not been verified by Google. However, this is fine as it is for personal use.

You can click ā€œAdvancedā€ in the lower left corner -> ā€œGo to Health Report (Responses) (unsafe)ā€

Click ā€œAllowā€

While the App Script is running, it will display ā€œRunning Script,ā€ please do not click again to avoid duplicate execution.

You can only execute it again after it shows successful execution.

Success! The submitted data has been grouped by date.

Comparing the Current Dateā€™s Sheet with the Employee List to Generate Unfilled List Sheet Data

Letā€™s add another piece of code:

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
// Compare with Employee List Sheet & Today's Submission Sheet to generate Unfilled List
function generateUnfilledList() {
  var listSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Employee List') // Name of Employee List Sheet
  var unfilledListSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Unfilled List') // Name of Unfilled List Sheet
  var today = new Date();
  var todayName = today.toLocaleDateString("en-US");

  var todayListSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(todayName) // Get today's MM/DD/YYYY Sheet
  if (todayListSheet == null) {
    SpreadsheetApp.getUi().alert('Cannot find the Sheet for '+todayName+' or please execute "Organize Submission Data" first');
    return;
  }

  var todayEmails = todayListSheet.getDataRange().getValues().map( x => x[1] ) // Get the list of Email Address data from today's Sheet (1 = Column B)
  // index starts from 0, so 1 = Column B
  // output: Email Address,zhgchgli@gmail.com,alan@gamil.com,b@gmail.com...
  todayEmails.shift() // Remove the first data, the first one is the column name "Email Address," which is meaningless
  // output: zhgchgli@gmail.com,alan@gamil.com,b@gmail.com...

  unfilledListSheet.clear() // Clear the Unfilled List... preparing to re-enter data
  unfilledListSheet.appendRow([todayName+" Unfilled List"]) // The first row displays the Sheet title

  var rows = listSheet.getDataRange().getValues(); // Read Employee List Sheet
  for(index in rows) {
    if (index == 0) { // The first row is the header row, store it so that subsequent data generation can also include the header
      unfilledListSheet.appendRow(rows[index]);
      continue;
    }
    
    if (todayEmails.includes(rows[index][3])) { // If this employee's Email is in today's Sheet Email Address, it means they have filled it out, continue to skip...
      continue;
    }

    unfilledListSheet.appendRow(rows[index]); // Write a row of data to the Unfilled List Sheet
  }
}

After saving, follow the previous method to add the code, then add another button and assign the script ā€” ā€œgenerateUnfilledList.ā€

Once completed, you can click to test:

The Unfilled List has been successfully generated! If no content appears, please ensure:

  • The Employee List has been filled out, or you can enter test data first
  • You must complete the ā€œOrganize Submission Dataā€ action first

Reading the Unfilled List Sheet to Compose a Message and Send it to a Designated Slack Channel

First, we need to add the Incoming WebHooks App to the Slack Channel, which we will use to send messages.

  1. In Slack, click ā€œAppsā€ in the lower left corner -> ā€œAdd appsā€
  2. Search for ā€œincomingā€ in the search box on the right
  3. Click ā€œIncoming WebHooksā€ -> ā€œAddā€

Select the Channel where you want to send the unfilled messages.

Note the ā€œWebhook URLā€ at the top

Scroll down to set the display name and profile picture for the Bot when sending messages; remember to click ā€œSave Settingsā€ after making changes.

Return to our Google Sheet Script

Add another piece of code:

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
function postSlack() {
  var ui = SpreadsheetApp.getUi();
  var result = ui.alert(
     'Are you sure you want to send the message?',
     'Send unfilled reminder message to Slack Channel',
      ui.ButtonSet.YES_NO);
  // To avoid accidental clicks, first ask for confirmation

  if (result == ui.Button.YES) {
    var unfilledListSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Unfilled List') // Name of Unfilled List Sheet
    var rows = unfilledListSheet.getDataRange().getValues();
    var persons = [];
    for(index in rows) {
      if (index == 0 || index == 1) { // Skip the header and column title rows
        continue;
      }
      
      var person = (rows[index][4] == "") ? (rows[index][2]) : ("<@"+rows[index][4]+">"); // Mark the target, if there is a slack uid, use it first; if not, just display the nickname; 2 = Column B / 4 = Column E
      if (person == "") { // If neither is present, consider it as abnormal data, ignore it
        continue;
      }
      persons.push("ā€¢ "+person+'\n') // Store the target in the array
    }

    if (persons.length <= 0) { // If there are no targets to be marked, it means everyone has filled it out, cancel the message sending
      return;
    }

    var preText = "*[Health Report Announcement:loudspeaker:]*\nThe company cares about everyone's health, please remind the following teammates to fill out their health status report daily, thank you:wink:\n\nToday's unfilled health status report list\n\n" // Message opening content...
    var postText = "\n\nFilling out the health status report allows the company to understand the physical condition of teammates, please ensure everyone fills it out daily >< Thank you all:woman-bowing::skin-tone-2:" // Message closing content...
    var payload = {
      "text": preText+persons.join('')+postText,
      "attachments": [{
          "fallback": "Here you can place the Google Form fill link",
          "actions": [
            {
                "name": "form_link",
                "text": "Go to Health Status Report",
                "type": "button",
                "style": "primary",
                "url": "Here you can place the Google Form fill link"
            }
          ],
          "footer": ":rocket:Tip: Click the input box below the " :zap:ļøLightning" -> "Shortcut Name" to fill it out directly."
        }
      ]
    };
    var res = UrlFetchApp.fetch('Enter your Slack incoming app Webhook URL here',{
      method             : 'post',
      contentType        : 'application/json',
      payload            : JSON.stringify(payload)
    })
  }
}

After saving, follow the previous method to add the code, then add another button and assign the script ā€” ā€œpostSlack.ā€

Once completed, you can click to test:

Success!!! (The display of @U123456 not successfully tagging the person is because the ID was randomly entered)

At this point, the main functionalities are complete!

Note

Please note that the official recommendation is to use the new Slack APP APIā€™s chat.postMessage to send messages. The convenient method of Incoming Webhook will be deprecated in the future. This was done for convenience and will need to be adjusted to the new method along with the next chapter ā€œImport Employee List.ā€

Importing Employee List

Here we need to create a Slack APP.

  1. Go to https://api.slack.com/apps

  2. Click ā€œCreate New Appā€ in the upper right corner

  1. Choose ā€œ From scratch ā€œ

  1. Enter ā€œ App Name ā€œ and the Workspace you want to add it to

  1. After successful creation, select ā€œOAuth & Permissionsā€ from the left menu for settings

  1. Scroll down to the Scopes section

Add the following items by clicking ā€œAdd an OAuth Scopeā€:

  1. Go back to the top and click ā€œInstall to workspaceā€ or ā€œReinstall to workspaceā€

*If Scopes are added, you need to reinstall it again.

  1. After installation, copy the Bot User OAuth Token

  2. Use the web version of Slack to open the Channel you want to import the list into ```

1
Get the URL from the browser:

https://app.slack.com/client/TXXXX/CXXXX

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
Where `CXXXX` is the Channel ID for this channel, make a note of this message.

10\.

Return to our Google Sheet Script

Add another piece of code:
```javascript
function loadEmployeeList() {
  var formData = {
    'token': 'Bot User OAuth Token',
    'channel': 'Channel ID',
    'limit': 500
  };
  var options = {
    'method' : 'post',
    'payload' : formData
  };
  var response = UrlFetchApp.fetch('https://slack.com/api/conversations.members', options);
  var data = JSON.parse(response.getContentText());
  for (index in data["members"]) {
    var uid = data["members"][index];
    var formData = {
      'token': 'Bot User OAuth Token',
      'user': uid
    };
    var options = {
      'method' : 'post',
      'payload' : formData
    };
    var response = UrlFetchApp.fetch('https://slack.com/api/users.info', options);
    var user = JSON.parse(response.getContentText());

    var email = user["user"]["profile"]["email"];
    var real_name = user["user"]["profile"]["real_name_normalized"];
    var title = user["user"]["profile"]["title"];
    var row = [title, real_name, real_name, email, uid]; // Fill in according to Column

    var listSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Employee List'); // Name of the Employee List Sheet
    listSheet.appendRow(row);
  }
}

But this time we donā€™t need to add a button, as the import only needs to be done the first time; just save the file and run it directly.

First, press ā€œcontrolā€ + ā€œsā€ to save, change the dropdown menu above to select ā€œloadEmployeeListā€, and click ā€œRunā€ to start importing the list into the Employee List Sheet.

Manually Add New Employee Data

If new employees join later, you can directly add a row in the Employee List Sheet and fill in the information. The Slack UID can be found directly on Slack:

Click on the person whose UID you want to view, then click ā€œView full profileā€

Click ā€œMoreā€ and select ā€œCopy member IDā€ to get the UID. UXXXXX

DONE!

All the above steps have been completed, and you can start automating the tracking of employee health status.

The completed file is available below; you can create a copy from the following Google Sheet to modify and use:

Additional Notes

  • If you want to use Scheduled date & time to send form messages regularly, note that in this case, the form can only be filled out once, so it is not suitable for use hereā€¦ (at least in the current version). Therefore, scheduled reminder messages still can only use plain text + Google Form links.

  • Currently, there is no way to link to a Shortcut to open the Form
  • Google Sheet App Script to prevent duplicate execution:

If you want to prevent accidentally pressing again during execution, which would cause duplicate execution, you can add the following at the beginning of the function:

1
2
3
4
5
if (PropertiesService.getScriptProperties().getProperty('FUNCTIONNAME') == 'true') {
  SpreadsheetApp.getUi().alert('Busy... please try again later');
  return;
}
PropertiesService.getScriptProperties().setProperty('FUNCTIONNAME', 'true');

At the end of the function, add:

1
PropertiesService.getScriptProperties().setProperty('FUNCTIONNAME', 'true');

Replace FUNCTIONNAME with the target function name.

Use a global variable to control execution.

This can be used to integrate CI/CD, wrapping the originally clunky command operations in a GUI, for example, in conjunction with the Slack Bitrise APP, using Slack Workflow forms to trigger Build commands:

After submission, it will send commands to a private channel with the Bitrise APP, e.g.:

1
bitrise workflow:app_store|branch:develop|ENV[version]:4.32.0

This will trigger Bitrise to execute the CI/CD Flow.

Further Reading

If you have any questions or suggestions, feel free to contact me.

If you have any automation-related optimization needs, feel free to hire me, thank you.

```


This article was first published on Medium āž”ļø Click Here

Automatically converted and synchronized using ZMediumToMarkdown and Medium-to-jekyll-starter.

Improve this page on Github.

Buy me a beer

2,375 Total Views
Last Statistics Date: 2025-03-25 | 2,133 Views on Medium.
This post is licensed under CC BY 4.0 by the author.