DEV Community

Cover image for Create A Sports Team Roster From Google Docs Template Using Google Sheets Data
nightwolfdev
nightwolfdev

Posted on • Originally published at nightwolf.dev

Create A Sports Team Roster From Google Docs Template Using Google Sheets Data

In this article, you’ll learn how to get player information from a Google Sheet and create a roster with it based on a Google Doc template! You’ll also learn how to create a custom menu in the spreadsheet to make it easy to create the roster. As a bonus, you’ll also learn how to email the roster as an attached pdf!

Roster Template Setup

Sports Team Roster Template

We need a template to base our roster on. Let’s start by creating a new Google Doc. You can make it look however you want. The important piece is where we want the table of player information to appear. Decide where that will be and type the following text in that location:



{{Players}}


Enter fullscreen mode Exit fullscreen mode

Later, we will look for this specific text and replace it with the actual table of player information.

Spreadsheet Setup

Sports Team Roster Spreadsheet Setup

  1. Create a sheet called Players.
  2. Create the following columns:
    • Jersey
    • First Name
    • Last Name

Script Editor

Google Apps Script Editor

Let’s start writing some code! Google Sheets has a handy script editor available.

  1. Navigate to Extensions > Apps Script.
  2. The script editor will include a starting function. You can remove all the code.
  3. Navigate to File > Save. Give the script project a name select Ok.

Get Players

Let’s create a function to return all of our player information. Create a function called getPlayers.



function getPlayers() {

}


Enter fullscreen mode Exit fullscreen mode

Within the getPlayers function, create a variable called rows and get all of the rows of data from the sheet called Players.



const rows = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Players').getDataRange().getValues();



Enter fullscreen mode Exit fullscreen mode

The Jersey column has numbers. Even if you format the column to be just numbers, no decimal places, it will still return a decimal. We don’t want to see jersey numbers with decimals in our final roster! To keep it simple, we’ll just convert every column value in every row to a string. Create a variable called data and map every column value in every row to a string.



const data = rows.map(row => row.map(val => val.toString()));


Enter fullscreen mode Exit fullscreen mode

All that is left to do is return the data.



return data;


Enter fullscreen mode Exit fullscreen mode

Here’s the final code for getPlayers.



function getPlayers() {
  const rows = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Players').getDataRange().getValues();
  const data = rows.map(row => row.map(val => val.toString()));
  return data;
}


Enter fullscreen mode Exit fullscreen mode

Style A Google Docs Table

We want a nice compact looking table with minimal padding. We’ll have to override the default table style with our own. Create a function called styleTable with an argument being passed in called table.



function styleTable(table) {

}


Enter fullscreen mode Exit fullscreen mode

Within the styleTable function, create a variable called rows and get the number of rows for the passed in table.



const rows = table.getNumRows();


Enter fullscreen mode Exit fullscreen mode

Styling involves defining an object where each property name is an attribue and the value is the new value to be applied. We want new styles for the column headings and each cell. Create two variables called headingStyle and cellStyle and assign empty objects to them.



const headingStyle = {};
const cellStyle = {};


Enter fullscreen mode Exit fullscreen mode

We want the column headings to be bold and the top and bottom padding of each cell to be smaller. Add the following:



headingStyle[DocumentApp.Attribute.BOLD] = true;
cellStyle[DocumentApp.Attribute.PADDING_TOP] = 0.025;
cellStyle[DocumentApp.Attribute.PADDING_BOTTOM] = 0.025;


Enter fullscreen mode Exit fullscreen mode

Apply the heading style to the first row of the table.



table.getRow(0).setAttributes(headingStyle);


Enter fullscreen mode Exit fullscreen mode

Apply the cell style to every cell. We have to loop through each row and cell in the table to apply it.



for (let r = 0; r < rows; r++) {
  const cols = table.getRow(r).getNumChildren();
  for (let c = 0; c < cols; c++) {
    const cell = table.getRow(r).getCell(c);
    cell.setAttributes(cellStyle);
  }
}


Enter fullscreen mode Exit fullscreen mode

Here’s the final code for styleTable.



function styleTable(table) {
  const rows = table.getNumRows();
  const headingStyle = {};
  const cellStyle = {};

  // Define custom styling
  headingStyle[DocumentApp.Attribute.BOLD] = true;
  cellStyle[DocumentApp.Attribute.PADDING_TOP] = 0.025;
  cellStyle[DocumentApp.Attribute.PADDING_BOTTOM] = 0.025;

  // Apply column heading style
  table.getRow(0).setAttributes(headingStyle);

  // Apply cell style
  for (let r = 0; r < rows; r++) {
    const cols = table.getRow(r).getNumChildren();
    for (let c = 0; c < cols; c++) {
      const cell = table.getRow(r).getCell(c);
      cell.setAttributes(cellStyle);
    }
  }
}


Enter fullscreen mode Exit fullscreen mode

Create Roster

We are now ready to create the roster based on the template and player information! Create a function called createRoster.



function createRoster() {

}


Enter fullscreen mode Exit fullscreen mode

Within the createRoster function, create a variable called ss, which will represent the spreadsheet. We will use a function provided by this object later.



const ss = SpreadsheetApp.getActiveSpreadsheet();


Enter fullscreen mode Exit fullscreen mode

Remember the function we created earlier to get player information? We’re ready to use it! Create a variable called players and call the getPlayers function.



const players = getPlayers();


Enter fullscreen mode Exit fullscreen mode

We need a folder to store the newly created roster. Pick a folder of your choice and get the folder’s id, which can be found in the url:



https://drive.google.com/drive/u/0/folders/FOLDER_ID_HERE


Enter fullscreen mode Exit fullscreen mode

Create a variable called folder and get the folder by its id.



const folder = DriveApp.getFolderById('FOLDER_ID_HERE');


Enter fullscreen mode Exit fullscreen mode

Remember the roster template we created earlier? We need that file’s id, which can be found in the url:



https://docs.google.com/document/d/FILE_ID_HERE/edit


Enter fullscreen mode Exit fullscreen mode

Create a variable called template and get the file by its id.



const template = DriveApp.getFileById('FILE_ID_HERE');


Enter fullscreen mode Exit fullscreen mode

Create a variable called templateCopy and make a copy of the template, give it a name, and store it in the folder we chose.



const templateCopy = template.makeCopy('Team Roster', folder);


Enter fullscreen mode Exit fullscreen mode

Create a variable called doc to get the newly created doc by its id.



const doc = DocumentApp.openById(templateCopy.getId());


Enter fullscreen mode Exit fullscreen mode

Create a variable called body to get the actual body of the document.



const body = doc.getBody();


Enter fullscreen mode Exit fullscreen mode

Remember the text we typed in the template for the location of where we wanted the player information to appear? Let’s look for that in the body and call it playersPlaceholder.



const playersPlaceholder = body.findText('{{Players}}');


Enter fullscreen mode Exit fullscreen mode

If we find the playersPlaceholder, we need to get its element, find where it’s located in the body and remove it, then insert the table of player information in its place. We also want to style the table using the styleTable function we created earlier.



if (playersPlaceholder) {
  const playersElement = playersPlaceholder.getElement();
  const playersIndex = body.getChildIndex(playersElement.getParent());

  body.getChild(playersIndex).removeFromParent();

  const playersTable = body.insertTable(playersIndex, players);
  styleTable(playersTable);
}


Enter fullscreen mode Exit fullscreen mode

Let’s save and close the document.



doc.saveAndClose();


Enter fullscreen mode Exit fullscreen mode

To show something happened in the spreadsheet, we can show a message to the user. We’ll show a different message depending on if there’s actually any players defined on the Players sheet. We check for a length greater than 1 because the first entry is the column headings.



if (players.length > 1) {
  ss.toast('Roster has been created!', 'Create Roster');
} else {
  ss.toast('No players defined.', 'Create Roster');
}


Enter fullscreen mode Exit fullscreen mode

Here’s the final code for createRoster.



function createRoster() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const players = getPlayers();

  const folder = DriveApp.getFolderById('FOLDER_ID_HERE');
  const template = DriveApp.getFileById('FILE_ID_HERE');

  const templateCopy = template.makeCopy('Team Roster', folder);
  const doc = DocumentApp.openById(templateCopy.getId());
  const body = doc.getBody();

  const playersPlaceholder = body.findText('{{Players}}');

  if (playersPlaceholder) {
    const playersElement = playersPlaceholder.getElement();
    const playersIndex = body.getChildIndex(playersElement.getParent());

    body.getChild(playersIndex).removeFromParent();

    const playersTable = body.insertTable(playersIndex, players);
    styleTable(playersTable);
  }

  doc.saveAndClose();

  if (players.length > 1) {
    ss.toast('Roster has been created!', 'Create Roster');
  } else {
    ss.toast('No players defined.', 'Create Roster');
  }
}


Enter fullscreen mode Exit fullscreen mode

Custom Menu

Let’s create a custom menu so we can create the roster from the spreadsheet’s menu toolbar instead!

The best time to create a custom menu is when the spreadsheet first opens. Use the onOpen trigger, which is executed when the spreadsheet is first opened.

Add a custom menu to the spreadsheet called Roster. Selecting the Roster menu will display a menu option called Create. Selecting Create will run the function called createRoster!



function onOpen() {
  const ui = SpreadsheetApp.getUi();

  ui.createMenu('Roster')
    .addItem('Create', 'createRoster')
    .addToUi();
}


Enter fullscreen mode Exit fullscreen mode

Email Roster

If you’d like to email the roster as a pdf attachment, here’s a function for that. Replace EMAIL_ADDRESS_HERE with the email address you want it to be sent to. If you want to delete the copy of the roster that was created in the folder, that line of code is also included in the function. You can remove it if you don’t want that to happen.



function emailRoster(doc) {
  const htmlBody = '<p>Attached is your team roster!</p>';

  if (MailApp.getRemainingDailyQuota() > 0) {
    MailApp.sendEmail('EMAIL_ADDRESS_HERE', 'Team Roster', '', { attachments: [doc.getAs('application/pdf')], htmlBody: htmlBody });
  }

  // Delete the document
  DriveApp.getFileById(doc.getId()).setTrashed(true);
}


Enter fullscreen mode Exit fullscreen mode

All that is left to do is add this function within the createRoster function right after saving and closing the doc.



doc.saveAndClose();

emailRoster(doc);


Enter fullscreen mode Exit fullscreen mode

Have fun creating your sports team roster!


Visit our website at https://nightwolf.dev and follow us on Twitter!

Top comments (0)