diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..7c12220338a44ac3ab82a7ed3d9cf70ad9ad03d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.xlsx diff --git a/__rechtsklick_ausfuehren_mit_powershell.ps1 b/__rechtsklick_ausfuehren_mit_powershell.ps1 new file mode 100644 index 0000000000000000000000000000000000000000..2be897a671796002a7deb55041f7aa66a6572766 --- /dev/null +++ b/__rechtsklick_ausfuehren_mit_powershell.ps1 @@ -0,0 +1,51 @@ + +# Define the registry path where R versions are typically installed +$rRegistryPath = "C:\Programme\R\" +# Get all subkeys (versions) under the R registry path +$rVersions = Get-ChildItem -Path $rRegistryPath | Where-Object { $_.PSChildName -like "R-*" } + +if ($rVersions.Count -gt 0) { + # sort for the latest version + $latestVersion = $rVersions | Sort-Object PSChildName -Descending | Select-Object -First 1 + $latestVersionPath = Join-Path -Path $rRegistryPath -ChildPath $latestVersion.PSChildName + + #combine the relative and the absolute path + $rScriptPath = Join-Path -Path $latestVersionPath -ChildPath "bin\Rscript.exe" + + Write-Host "Hello User:" + Write-Host "You are using the following Version of R:: $($latestVersion.PSChildName)" + Write-Host "###################################################" + Write-Host "After new installation of R and if you see the following output:" + Write-Host "Fehler in ... Ausfuehrung angehalten" + Write-Host "You have to open the Script over R-Studio and install the packages over it." + Write-Host "###########################################################################" + Write-Host "" + + # Use Start-Process to execute the R script using Rscript.exe + # Start-Process -FilePath $rScriptPath -ArgumentList $rScriptFileWithCompletePath + #-> this command didnt work + + # Specify the argument to pass to the R script + $argument = "TRUE" + + # Use & operator to execute the R script using Rscript.exe with the file path and argument + #Specify the path to the R script file + + #Full path: + #$rScriptFileWithCompletePath = "P:/IMEBI/DigiHero_Teilnehmerdaten/Massenmails/_neu_TOKENAUFBEREITER_Umfrageteilnehmertabellen/main.R" + #& $rScriptPath $rScriptFileWithCompletePath $argument + + #path with the file in the current working directory + $rScriptFile ="main.R" + & $rScriptPath $rScriptFile $argument + + + + + + +} else { + Write-Host "No R version found in:: C:\Programme\R\" +} + + diff --git a/download_get_key.R b/download_get_key.R new file mode 100644 index 0000000000000000000000000000000000000000..d1a8677495ad3cf6e181ad9d9fc7e129edeb45fd --- /dev/null +++ b/download_get_key.R @@ -0,0 +1,24 @@ + +#install and load packages +if (!require("devtools")) { + install.packages("devtools") + library("devtools") +} +if (!require("cloudyr/limer")) { + install_github("cloudyr/limer") + library("jsonlite") + library("limer") +} + +# !ACHTUNG: PASSWORT UND USERNAME MÜSSEN NOCH BEHANDELT WERDEN! +# SICHERHEITSRISIKO BEI FEST EINKODIERTEN WERTEN + +#Der Benutzer R_Export hat auf einzelnen Umfragen ausschließlich Rechte: Anzeigen + +#change the next options (website, user, password) +options(lime_api = 'https://webszh.uk-halle.de/limesurvey/index.php/admin/remotecontrol') +options(lime_username = 'R_Export') +options(lime_password ='Export2023') + +# first get a session access key +get_session_key() diff --git a/function_load.R b/function_load.R new file mode 100644 index 0000000000000000000000000000000000000000..beb9b38c3ebd77d293007503a61f646a643b07d1 --- /dev/null +++ b/function_load.R @@ -0,0 +1,341 @@ + +# Check if the programm is started with powershell +use_powershell <- FALSE + +if (length(commandArgs(trailingOnly = TRUE)) > 0) { + # Get the command-line arguments + + # bei dem Aufruf mit PowerShell wird TRUE übergeben + use_powershell <<- commandArgs(trailingOnly = TRUE) + + # Process the command-line arguments + #for (arg in args) { + # print(arg)} + cat("\n") + cat("####\n") + cat("command-line arguments provided.: ") + print(use_powershell) + cat("####\n") + cat("\n") +} else { + cat("\n") + cat("####\n") + cat("No command-line arguments provided.\n") + cat("-> You are using an incomplete powershell command or R-Studio.\n") + cat("####\n") + cat("\n") + # the powershell command must be handed over in the following form : Rscript your_script.R arg1 arg2 arg3 +} + +#create global variable for the readline-command +choice <- T + + + + +#first: define all functions: +function_read_prompt <- function(){ + + if(use_powershell){ + # Read input from file or standard input + input <- file("stdin") + + # Print prompt and read user input + cat("PS::EINGABE:") + choice <<- scan(input, what = "character", n = 1) + + # Close input connection + close(input) + } + else{ + + #this command did not work properly using Powershell. + #so it is important to change the readline path depending on the environment + # <<- so it is possible to change the global variable + choice <<- readline(prompt = "rl::EINGABE:") + + } +} + + +function_start <- function(){ + + # User interaction to choose a function + cat("\n") + cat("Die erforderlichen Vorarbeiten wurden erledigt: welche nachfolgenden Schritte sollen unternommen werden?\n") + cat("\n") + cat("Bitte wähle einen Pfad aus:\n") + cat("----------------------------\n") + cat("1 = Tokenaufbereiter alle TN:\n") + cat(" wird verwendet, wenn alle registrierten Personen zu einer Umfrage eingeladen werden sollen.\n") + cat("-------------------------------------------------------------------------------------------------------------------\n") + cat("2 = Tokenaufbereiter Newsletter:\n") + cat(" wird zum Newsletterversand verwendet.\n") + cat(" Es werden bereits alle Personen entfernt, die keinen Newsletter mehr erhalten wollen.\n") + cat(" Die Liste für die Abmeldung vom Newsletter wird von Mareike gewartet.\n") + cat(" Die Datei: P://IMEBI//DigiHero_Teilnehmerdaten//Newsletter_Abmeldung.xlsx wird automatisch eingelesen.\n") + cat("-------------------------------------------------------------------------------------------------------------------\n") + cat("3 = Tokenaufbereiter MIT HHID als firstname:\n") + cat(" wird verwendet, wenn TN angeschrieben werden, bei denen in der Mail eine Haushalts-ID angegeben wird.\n") + cat(" Tokenliste + zugehörige Haushalts-ID erhält man von den wissenschaftlichen Mitarbeiter*innen.\n") + cat("-------------------------------------------------------------------------------------------------------------------\n") + cat("4 = Tokenaufbereiter OHNE HHID:\n") + cat(" wird verwendet, wenn TN angeschrieben werden, bei denen in der Mail keine Haushalts-ID angegeben wird.\n") + cat(" Tokenliste OHNE Haushald-ID erhält man von den wissenschaftlichen Mitarbeiter*innen\n") + cat("-------------------------------------------------------------------------------------------------------------------\n") + cat("9 = mir ist ein Fehler passiert. Es wird nichts gespeichert!\n") + + function_read_prompt() + + if (!choice %in% c("1","2","3","4","9")){ + cat("\n") + cat("\n") + cat("##################\n") + cat("Ungültige Auswahl! Bitte verwende: 1, 2, 3, 4 oder 9. Danke.\n") + cat("##################\n") + cat("\n") + cat("\n") + function_start() + } + else{ + # Convert user input to integer + choice <- as.integer(choice) + if (choice == 1) { + function_Tokenaufbereiter_alle_TN() + } else if (choice == 2) { + function_Tokenaufbereiter_Newsletter() + } else if (choice == 3) { + function_Tokenaufbereiter_MIT_HHID_als_firstname() + } else if (choice == 4) { + function_Tokenaufbereiter_OHNE_HHID() + } else { + function_exit() + } + + } +} + +function_Tokenaufbereiter_alle_TN <- function() { + cat("\n") + cat("Tokenaufbereiter alle TN\n") + cat("------------------------\n") + cat("Es sind keine weiteren Schritte notwendig!\n") + cat("\n") + + combined_token_with_download <- cleaned_df + + # zeilennummer erzeugen + combined_token_with_download <- combined_token_with_download %>% mutate(id = row_number()) + + #relocate + combined_token_with_download <- combined_token_with_download |> relocate(token, .after = emailstatus) + combined_token_with_download <- combined_token_with_download |> relocate(id, .before = firstname) + + #save the file + #setwd("H:/01_Limesurvey_TokenVergleich") + write_xlsx(combined_token_with_download,paste0("./Umfrageteilnehmertabelle_",format(Sys.Date(), "%Y_%m_%d"),"_alle_TN.xlsx")) + + + function_end() + +} + +function_Tokenaufbereiter_Newsletter <- function() { + cat("\n") + cat("Tokenaufbereiter Newsletter\n") + cat("---------------------------\n") + cat("Die Liste für die Abmeldung vom Newsletter wird von Mareike gewartet.\n") + cat("Die Datei: P://IMEBI//DigiHero_Teilnehmerdaten//Newsletter_Abmeldung.xlsx wird automatisch eingelesen.\n") + #cat("In der Regel findet sich die Datei in:\n") + #cat("P:\\IMEBI\\DigiHero\\10_Auswertung\\Datenablage für MK und YF\\Newsletter_ohne_TH.xlsx \n") + if(use_powershell){ + cat("Fortfarhren? Press [y + ENTER]. Ansonsten kann das Script mit Eingabe von [e + ENTER] beendet werden\n") + }else{ + cat("Fortfarhren? Press [ENTER]. Ansonsten kann das Script mit Eingabe von [e + ENTER] beendet werden\n") + } + function_read_prompt() + + if (choice == "y" || choice == ""){ + #Eingabe: [ENTER] -> weiter gehts + + #laden und joinen + #token_list <- read_xlsx(file.choose()) + #combined_token_with_download <- inner_join(token_list,cleaned_df, by="token") + combined_token_with_download <- cleaned_df + + # zeilennummer erzeugen + combined_token_with_download <- combined_token_with_download %>% mutate(id = row_number()) + + #relocate + combined_token_with_download <- combined_token_with_download |> relocate(token, .after = emailstatus) + combined_token_with_download <- combined_token_with_download |> relocate(id, .before = firstname) + + #specific deletion + token_for_newsletter_to_remove <- read_xlsx("P:/IMEBI/DigiHero_Teilnehmerdaten/Newsletter_Abmeldung.xlsx", sheet="combined") + + #tokens_to_remove <- c("fcNJSEZXp6aja09", "i2UWfmddV8IDv52", "7jBwCVzYVy1BHKz", "9WRI8lvhqufm9zE", + # "uVfhUNYG8UePYfy", "il1xCGz2nB30Cvg", "2t06iU8tbN6Gsdb", "iydZWTsI3f4dC2z") + + #filter alle gegebenen token aus der der Newsletter_Abmeldung heraus + combined_token_with_download <- combined_token_with_download %>% + filter(!token %in% token_for_newsletter_to_remove$token) + + #save the file + #setwd("H:/01_Limesurvey_TokenVergleich") + write_xlsx(combined_token_with_download,paste0("./Umfrageteilnehmertabelle_",format(Sys.Date(), "%Y_%m_%d"),"_Newsletter.xlsx")) + + function_end() + + } else{ + #Eingabe: irgendwas ausser [ENTER] -> Abbruch + function_exit() + } +} + + +function_Tokenaufbereiter_MIT_HHID_als_firstname <- function() { + cat("\n") + cat("Tokenaufbereiter MIT HHID als firstname\n") + cat("---------------------------------------\n") + cat("Die Tokenlisten werden von den wissenschaftlichen Mitarbeiter*innen erstellt.\n") + cat("In der Regel findet sich die Datei in:\n") + cat("P:\\IMEBI\\DigiHero\\10_Auswertung\\Datenablage für MK und YF\\LC_Token_Baseline_KurzeBefragung_2023-01-17.xlsx \n") + + if(use_powershell){ + cat("Hast du die Datei? Press [y + ENTER]. Ansonsten kann das Script mit Eingabe von [e + ENTER] beendet werden\n") + }else{ + cat("Hast du die Datei? Press [ENTER]. Ansonsten kann das Script mit Eingabe von [e + ENTER] beendet werden\n") + } + function_read_prompt() + + if (choice == "y" || choice == ""){ + #Eingabe: [ENTER] -> weiter gehts + + #laden und joinen + token_list <- tryCatch({ + read_xlsx(file.choose()) + }, error = function(e) { + message("Failure: ",conditionMessage(e)) + NULL + function_exit() + }) + + combined_token_with_download <- inner_join(token_list,cleaned_df, by="token") + + #rename + combined_token_with_download <- combined_token_with_download %>% + rename(first = firstname) + combined_token_with_download <- combined_token_with_download %>% + rename(last = lastname) + combined_token_with_download$lastname <- paste(combined_token_with_download$first, + combined_token_with_download$last, sep = " ") + combined_token_with_download <- combined_token_with_download %>% + rename(firstname = hhid) + combined_token_with_download$first <- NULL + combined_token_with_download$last <- NULL + + # zeilennummer erzeugen + combined_token_with_download <- combined_token_with_download %>% mutate(id = row_number()) + + #relocate + combined_token_with_download <- combined_token_with_download |> relocate(id, .before = firstname) + combined_token_with_download <- combined_token_with_download |> relocate(lastname, .after = firstname) + combined_token_with_download <- combined_token_with_download |> relocate(token, .after = emailstatus) + + #save the file + #setwd("H:/01_Limesurvey_TokenVergleich") + write_xlsx(combined_token_with_download,paste0("./Umfrageteilnehmertabelle_",format(Sys.Date(), "%Y_%m_%d"),"_mit_HHID_as_firstname.xlsx")) + + function_end() + + } else{ + #Eingebe: irgenwas auser [ENTER] -> Abbruch + function_exit() + } +} + +function_Tokenaufbereiter_OHNE_HHID <- function() { + cat("\n") + cat("Tokenaufbereiter OHNE HHID\n") + cat("--------------------------\n") + cat("Die Tokenlisten werden von den wissenschaftlichen Mitarbeiter*innen erstellt.\n") + cat("In der Regel findet sich die Datei in:\n") + cat("P:\\IMEBI\\DigiHero\\10_Auswertung\\Dunkelziffer_Immunstatus\\Token_Auswahl_DBS\\Token_DigiHero_Immunstatus_DBS_1500.xlsx \n") + if(use_powershell){ + cat("Hast du die Datei? Press [y + ENTER]. Ansonsten kann das Script mit Eingabe von [e + ENTER] beendet werden\n") + }else{ + cat("Hast du die Datei? Press [ENTER]. Ansonsten kann das Script mit Eingabe von [e + ENTER] beendet werden\n") + } + + function_read_prompt() + + if (choice == "y" || choice == ""){ + #Eingabe: [ENTER] -> weiter gehts + + #laden und joinen + token_list <- tryCatch({ + read_xlsx(file.choose()) + }, error = function(e) { + message("Failure: ",conditionMessage(e)) + NULL + function_exit() + }) + combined_token_with_download <- inner_join(token_list,cleaned_df, by="token") + + # zeilennummer erzeugen + combined_token_with_download <- combined_token_with_download %>% mutate(id = row_number()) + + #relocate + combined_token_with_download <- combined_token_with_download |> relocate(token, .after = emailstatus) + combined_token_with_download <- combined_token_with_download |> relocate(id, .before = firstname) + + + #save the file + setwd("H:/01_Limesurvey_TokenVergleich") + write_xlsx(combined_token_with_download,paste0("./Umfrageteilnehmertabelle_",format(Sys.Date(), "%Y_%m_%d"),"_ohne_HHID.xlsx")) + + function_end() + + } else{ + #Eingabe: irgenwas auser [ENTER] -> Abbruch + function_exit() + } + + +} + + +function_exit <- function() { + cat("\n") + cat("Script wird beendet. Es erfolgt keine Speicherung irgendwelcher Dateien.\n") + if(use_powershell){ + cat("Press [y + ENTER] to quit the Script without saving informations.\n") + cat("I wish you a wonderfull day!: ") + function_read_prompt() + quit() + } else{ + cat("Press [ENTER] to quit the Script without saving informations.\n") + cat("I wish you a wonderfull day!: ") + function_read_prompt() + #dont use quit() -> it restarts your R-Studio + } + + + +} + +function_end <- function(){ + cat("\n") + cat("Es wurde alle notwendigen Schritte zur Bearbeitung und Speicherung unternommen.\n") + if(use_powershell){ + cat("Press [y + ENTER] to quit the Script.\n") + cat("I wish you a wonderfull day!: ") + function_read_prompt() + quit() + } else{ + cat("Press [ENTER] to quit the Script.\n") + cat("I wish you a wonderfull day!: ") + function_read_prompt() + #dont use quit() -> it restarts your R-Studio + } +} \ No newline at end of file diff --git a/main.r b/main.r new file mode 100644 index 0000000000000000000000000000000000000000..e726bb6333d9eedc4d2ba7eded9282108fd8137c --- /dev/null +++ b/main.r @@ -0,0 +1,182 @@ + +# reset workspace #### +rm(list=ls()) + +#setwd #### +setwd("P:/IMEBI/DigiHero_Teilnehmerdaten/Massenmails/_neu_TOKENAUFBEREITER_Umfrageteilnehmertabellen") + +cat("\n") +cat("Hallo Benutzer*in: Du hast das Script für den Tokenaufbereiter gestartet.\n") +cat("Nachfolgend werden jetzt:\n") +cat("- Alle notwendigen Pakete geladen.\n") +cat("- Alle erforderlichen Teilnehmerdaten aus den nachfolgenden Umfragen heruntergeladen.\n") +cat("+ 433442\n") +cat("+ 144481\n") +cat("+ 538473\n") +cat("-> Dauert ca. 10-20 Sekunden.\n") +cat("\n") +cat("####\n") +cat("At the end, the files are stored in the following working directory:\n") +cat("P:/IMEBI/DigiHero_Teilnehmerdaten/Massenmails/_neu_TOKENAUFBEREITER_Umfrageteilnehmertabellen/\n") +cat("####\n") +suppressWarnings({ +suppressMessages({ +#### DOWNLOAD Vorarbeit#### +library(readxl) +library(writexl) +library(tidyverse) + +#Start with user interaction: Pfad in Abhängigkeit von der Aufgabe wählen #### + +source("./function_load.R") + +#get download key# +source("./download_get_key.R") +}) +}) +#### DOWNLOAD Ausführung### + +#Umfragen ID: +# 433442 +# |> diese Umfrage staret bei ID 43 und endet bei: 92813 (Stand: März 2024) +# |> Funktion: get_last_id habe nicht gefunden. Wert muss daher im Skript manuell angepasst werden. +# 144481 +# 538473 + + +#Vorlage für Download von den Antworten der Teilnehmer### +#ls_433442_0 <- get_responses(iSurveyID= 433442, sLanguageCode= 'de', sResponseType='short', +# iFromResponseID =1, +# iToResponseID=50) + +#Download der Daten der Umfrageteilnehmer selbst### +#Schleife geht nicht -> keine Ahung warum +# for(i in 1:2){ +# paste0(lp,i)<- get_participants(iSurveyID = 433442,iStart=as.Integer(paste0(i,0001)),iLimit =as.Integer(paste0(i+1,0000)), bUnused=FALSE, aAttributes=FALSE) +# #lp1<- get_participants(iSurveyID = 433442,iStart=20001,iLimit = 20000, bUnused=FALSE, aAttributes=FALSE) +# } +#wenn iLimit > 50.000 gibt es eine Fehlermeldung + +#problem: token, firstname, etc. gets automatic downloaded +# you have to added the extra columns that needed +atr <- c( + "emailstatus", + "language" + ) +# nach Mareikes Skript wird nur die Spalte "language" und "emailstatus" benötigt +# -> emailstatus beinhaltet die Information "INVALID", damit Limesurvey keine Mails an diese Adressen sendet. +#atr <- c( +# "emailstatus", "language","validfrom","validuntil","remindercount","completed","invited","reminded","usesleft") +# Die folgenden Spalten werden nicht geladen -> keine Ahnung warum. Sie werden auch nicht geladen, wenn man nur diese eingibt. +# Es gibt aber anscheinend keine implizite Mengenbeschränkung. +#"invited", +#"reminded", + +p_433442_00<- get_participants(iSurveyID = 433442,iStart=1,iLimit = 50000, bUnused=FALSE, aAttributes=atr) +p_433442_01<- get_participants(iSurveyID = 433442,iStart=50001,iLimit = 100000, bUnused=FALSE, aAttributes=atr) +cat("####\n") +cat("Der größte Wert aus der Umfrage 433442 zeigt: ") +print(max(p_433442_01$tid, na.rm = TRUE)) +if(max(p_433442_01$tid, na.rm = TRUE)>=99500){ + cat("Die tid der Tabelle 433442 steht kurz vor 100.000 -> nochmal im Skript schauen, damit der Ablauf passt.\n") + cat("Nachdem tid >= 100.001 wird die dritte Datei der Umfrage 433442 geladen und nicht mehr gelöscht.\n") +} +cat("####\n") +cat("\n") +#Umfrage zum Zeitpunkt des Scriptes noch leer +#Die Datei enhält eine Spalte mit name status : "No survey participants found." +p_433442_02 <- get_participants(iSurveyID = 433442,iStart=100001,iLimit = 150000, bUnused=FALSE, aAttributes=FALSE) +#daher: solange die Tabelle leer ist, wird sie gleich wieder gelöscht +if("status" %in% colnames(p_433442_02)){ + rm(p_433442_02) +}else if (max(p_433442_02$tid, na.rm = TRUE)>=0){ + cat("Das Skript lädt jetzt den 3.Teil der Umfrage: 433442\n") + cat("Das aktuelle Tid beträgt:") + print(max(p_433442_02$tid, na.rm = TRUE)) + cat("\n") +} + + +p_144481_00 <- get_participants(iSurveyID = 144481,iStart=1,iLimit = 50000, bUnused=FALSE, aAttributes=atr) + +p_538473_00<- get_participants(iSurveyID = 538473,iStart=1,iLimit = 50000, bUnused=FALSE, aAttributes=atr) + +#erste Idee für die Weiterarbeit #### +#binden und "tid" entfernen +#token144481 <- read.csv("tokens_144481.csv") +#token433442 <- read.csv("tokens_433442.csv") +#token538473 <- read.csv("tokens_538473.csv") +#token <- bind_rows(token144481,token433442,token538473) +#token <- token |> select (-c(tid)) |> distinct() + +#alle "Test"-Zeilen entfernen +#TestTokens NUR über firstname identifizieren +#token<- token |> filter(!str_detect(tolower(firstname), 'test')) + + +cat("####\n") +cat("Der Download wurde abgeschlossen.\n") +cat("Nun werden die heruntergeladen Tabellen verbunden.\n") +cat("####\n") + + + +#Daten Verarbeiten#### +# Verbinden was ein data.frame ist. +# in diesem Code gibt es eh nur data.frame +filtered_data_frames <- Filter(function(x) is.data.frame(get(x)), ls()) + +# die "values" zu "Data" machen und die participant_info entschachteln +data_frames_list <- lapply(filtered_data_frames, get) +suppressWarnings({ + +data_frames_list2 <- lapply(data_frames_list, unnest) +}) +# zusammenhängendes data.frame erzeugen, tid entfernen und doppelte werte löschen +combined_df <- do.call(rbind, data_frames_list2) +combined_df$tid <- NULL +unique_df <- combined_df[!duplicated(combined_df), ] + +#löschen der Testdaten +values_to_delete = c("Test1","Test2","Test3","Test4","Test5","Test6","Test7","Test8","Test9", + "Test10","Test11","Test12","test","Test","Test Bestätigungsmail","Mareike Test", + "Test Mareike","Bianca TEST","AlexandraTest") + +removed_test_values <- unique_df[!unique_df$firstname %in% values_to_delete, ] + +#SAS und Anführungszeichen -> entfällt hier in R #### + +#Umlaute ersetzen#### + + +cleaned_df <- removed_test_values |> mutate(across(firstname | lastname, + \(x) stringr::str_replace_all(string = x, + c('ä' = 'ae', + 'ë' = 'ee', + 'ï' = 'ie', + 'ü' = 'ue', + 'ö' = 'oe', + 'ß' = 'ss', + 'ö' = 'oe', + '`' = '', + '´' = '', + 'š' = 's', + 'Ž' = 'z', + '–' = '-', + 'õ' = 'oe' + )))) + +#Die nicht geladenen Spalten neu einbinden und mit festen Werten speichern#### +#Enstprechend der alten Vorgaben im SAS-Script von Mareike + +cleaned_df$validfrom <- "" +cleaned_df$validuntil <- "" +cleaned_df$invited <- "N" +cleaned_df$reminded <- "N" +cleaned_df$remindercount <- "0" +cleaned_df$completed <- "N" +cleaned_df$usesleft <- "1" + + + +function_start() \ No newline at end of file