Zum Inhalt springen

Re-connecting Google Contacts and Calendar

For some „regulatory“ reason Google Calendar in Germany no longer shows the birthdays of Google Contacts. There was earlier this year a workaround described to change the setting here and the connection should work again.

As of October 2024 this no longer works for me and the Google website says that due to an agreement with a German regulator this feature is no longer available.

So here is my workaround how to fix it:

Create a new Google Sheet and create a new App Script.

In the App Script under Services enable the People Service.

Now copy the code below into the Editor:

App Script Source code
// Calendar 2 Contact - automatically creating Birthday Entries from contacts
// Copyright (C) 2024, Oliver Bossert

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

function createBirthdayEvents() {
  // Get the active spreadsheet and sheet
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getActiveSheet();

  // Get the last row with data
  var lastRow = sheet.getLastRow();

  // Iterate through each row starting from the second row (assuming header is in the first row)
  for (var i = 2; i <= lastRow; i++) {
    // Get the birthday data as a string
    var birthdayData = sheet.getRange(i, 2).getValue();
    Logger.log(birthdayData)

    // Parse the birthday data
    var birthdayObj = extractDayMonthYear(birthdayData);

    // Handle missing year
    var year = birthdayObj.year || new Date().getFullYear();

    // Create a Date object from the parsed data
    var birthdayDate = new Date(year, birthdayObj.month - 1, birthdayObj.day);


    // Create a Calendar event  
    const recurrence = CalendarApp.newRecurrence().addYearlyRule();

    var event = CalendarApp.createAllDayEventSeries(
      "🎂 " + sheet.getRange(i, 1).getValue(),
      birthdayDate,
      recurrence,
      {
        eventType: 'birthday',
        visibility: 'private',
        transparency: 'transparent',
      }
    );
    event.setColor('9');
    event.removeAllReminders();
  }
}


function extractDayMonthYear(inputString) {
  var day, month, year;
  var matches = inputString.match(/(\w+)=(\d+\.\d+)/g);

  if (matches) {
    for (var i = 0; i < matches.length; i++) {
      var match = matches[i].split('=');
      var key = match[0];
      var value = parseFloat(match[1]);

      switch (key) {
        case 'day':
          day = value;
          break;
        case 'month':
          month = value;
          break;
        case 'year':
          year = value;
          break;
        default:
          // Handle unexpected keys if needed
          break;
      }
    }
  }

  // Set missing year to 1900
  year = year || 1900;

  return {
    day: day,
    month: month,
    year: year
  };
}


function getContactsAndBirthdays() {
  // Get a list of all contacts
  var contacts = People.People.Connections.list('people/me', {
      personFields: 'names,birthdays'
    });

  // Create a new spreadsheet
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); //create('Contacts and Birthdays');

  // Get the first sheet
  var sheet = spreadsheet.getSheets()[0];

  // Set the header row
  sheet.getRange(1, 1, 1, 2).setValues([['Name', 'Birthday']]);

  // Iterate over the contacts and add them to the spreadsheet
  var row = 2;
  while (contacts) {
    for (var i = 0; i < contacts.connections.length; i++) {
      var contact = contacts.connections[i];
    var name = "";
    if (contact.names && contact.names.length > 0) {
      name = contact.names[0].displayName;
    }
      var birthday = "";
      if (contact.birthdays && contact.birthdays.length > 0) {
        birthday = contact.birthdays[0].date;
      }
      sheet.getRange(row, 1, 1, 2).setValues([[name, birthday]]);
      row++;
    }

    // Get the next page of contacts
    if (contacts.nextPageToken) {
      contacts = People.People.Connections.list('people/me', {
        personFields: 'names,birthdays',
        pageToken: contacts.nextPageToken
      });
    } else {
      contacts = null;
    }
  }
}

Then select getContactsAndBirthdays() as a function and select ‚Run‘. After accepting multiple Access questions from Google (always click yes…) you should have a list of Names and weirdly formatted dates in the spreadsheet.

Now you can (and should) clean up the list and remove all entries with an empty date column as well as those people you don’t want to have in your calendar.

After the cleanup go back in the AppScript window and select the createBirthdayEvents() function and run it. Now you should have all relevant birthdays in your calendar.

Published inSoftware

Sei der Erste der einen Kommentar abgibt

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert