#' Write a printable PDF file.
#'
#' A utility to generate a PDF file ready for printing labels.
#'
#' This function generates a PDF document that can be printed directly to sheets
#' of labels/stickers for the easy and clear identification of experimental
#' samples. The default behaviour is to print the same ID across all labels in a
#' row, with a different ID for each row.
#'
#'
#' @param ids A character vector of IDs as generated by
#' \code{\link[idLabelR]{make_ids}}.
#' @param layout A \code{\link{list}} object describing the layout of labels on
#' the sheet to be printed. See Details to learn how to customise this.
#' @param byRow By default (\code{byRow = TRUE}), IDs are repeated for all
#' labels in a row. If \code{byRow = FALSE}, then IDs are repeated for all
#' labels in a column. It is also possible to set \code{byRow = NULL}, which
#' will print each ID on one label only.
#' @param sublabel An optional character vector that will be printed under the
#' ID. This allows the replicate label (for the same ID) to be distinguished
#' (to label, for example, different samples, tissues, replicate numbers,
#' collection sites or dates). When \code{byRow} is TRUE, then this vector
#' should be the same length as the number of columns in the label layout; or
#' the length of the number of rows if \code{byRow} is FALSE. If \code{byRow}
#' is NULL, then specify only one sublabel (if a vector is supplied, only the
#' first element will be used).
#' @param printing An optional character to identify multiple copies of the same
#' label sheet. Default is to ignore this feature.
#' @param file The name of the file to be written to. The default is
#' \code{"Labels.pdf"} in the current working directory.
#' @param ... Additional parameters passed to \code{\link[grDevices]{pdf}}.
#'
#' @seealso \code{\link[idLabelR]{make_ids}}. Also see
#' \code{\link[grDevices]{pdf}} for detail on additional PDF printing
#' parameters.
#'
#' @examples
#' require(idLabelR)
#' example_spreadsheet = system.file("extdata", "Example.txt", package = "idLabelR")
#' ids = make_ids(file = example_spreadsheet)
#' layout = get_layout("cryobabies_LCRY_1700_A4")
#' make_pdf(ids, layout)
#'
#' # Additionally prints a timestamp and identifier
#' # to distinguish repeated printings of the same page.
#' make_pdf(ids, layout, printing = "a")
#'
#' # 17 rows of 5 labels for each ID.
#' make_pdf(ids, layout, byRow = TRUE, file = "Labels_by_row.pdf")
#' # 5 columns of 17 labels for each ID.
#' make_pdf(ids, layout, byRow = FALSE, file = "Labels_by_col.pdf")
#'
#' @importFrom grDevices pdf dev.off
#' @importFrom graphics par text
#' @importFrom tools file_path_sans_ext
#'
#' @export
make_pdf = function(ids, layout, byRow = TRUE, sublabel = NULL, printing = NULL, file = "Labels.pdf", ...){
if(layout$units == "mm"){
layout$page.width = layout$page.width / 25.4
layout$page.height = layout$page.height / 25.4
layout$label.x = layout$label.x / 25.4
layout$label.y = layout$label.y / 25.4
layout$timestamp.x = layout$timestamp.x / 25.4
layout$timestamp.y = layout$timestamp.y / 25.4
}
# Format sublabel.
if(is.null(byRow)){ # Print one copy only of each label.
sublabel = as.character(sublabel)[1] # Only one value used, and repeated for all labels.
}else if(byRow){
sublabel = paste0(rep("", length(layout$label.x)), as.character(sublabel))[seq_along(layout$label.x)]
}else{
sublabel = paste0(rep("", length(layout$label.y)), as.character(sublabel))[seq_along(layout$label.y)]
}
if(!is.null(printing)) printing = paste0("_", printing)
split.vector = function(v, n){
ncols = floor(length(v)/n)
remainder = NULL
if(ceiling(length(v)/n) > ncols) remainder = list(v[(n * ncols + 1):length(v)])
if(ncols > 0){
return(unname(c(split(v[1:(n * ncols)], rep(1:ncols, each=n)), remainder)))
}else{
return(unname(list(v[(n * ncols + 1):length(v)])))
}
}
if(is.null(byRow)){
pages = split.vector(ids, n = length(layout$label.x) * length(layout$label.y))
grDevices::pdf(file = paste0(tools::file_path_sans_ext(file), printing, ".pdf"), width = layout$page.width, height = layout$page.height)
graphics::par(mar = c(0, 0, 0, 0))
for(p in seq_along(pages)){
n = 1
plot(0, xlim=c(0, layout$page.width), ylim=c(layout$page.height, 0), ann=F, bty="n", type="n", xaxt = "n", yaxt = "n", xaxs = "i", yaxs = "i")
for(y in layout$label.y){
for(xi in seq_along(layout$label.x)){
text = pages[[p]][n]
x = layout$label.x[xi]
graphics::text(x, y, text, adj = c(0.5, NA), cex = layout$text.size, font = layout$text.font)
graphics::text(x, y, as.character(sublabel), adj = c(0.5, layout$sublabel.offset), cex = layout$sublabel.size, font = layout$sublabel.font)
n = n + 1
}
}
# Add vertical date and sheet stamp.
if(!is.null(printing) & !is.null(layout$timestamp.x) & !is.null(layout$timestamp.y) & !is.null(layout$timestamp.size)){
graphics::text(layout$timestamp.x, layout$timestamp.y, paste0("Page ", p, printing, " ", Sys.Date()), adj = c(0, 0), cex = layout$timestamp.size, srt = -90)
}
}
}else if(byRow){
pages = split.vector(ids, n = length(layout$label.y))
grDevices::pdf(file = paste0(tools::file_path_sans_ext(file), printing, ".pdf"), width = layout$page.width, height = layout$page.height)
graphics::par(mar = c(0, 0, 0, 0))
for(p in seq_along(pages)){
n = 1
plot(0, xlim=c(0, layout$page.width), ylim=c(layout$page.height, 0), ann=F, bty="n", type="n", xaxt = "n", yaxt = "n", xaxs = "i", yaxs = "i")
for(y in layout$label.y){
text = pages[[p]][n]
for(xi in seq_along(layout$label.x)){
x = layout$label.x[xi]
graphics::text(x, y, text, adj = c(0.5, NA), cex = layout$text.size, font = layout$text.font)
graphics::text(x, y, as.character(sublabel[xi]), adj = c(0.5, layout$sublabel.offset), cex = layout$sublabel.size, font = layout$sublabel.font)
}
n = n + 1
}
# Add vertical date and sheet stamp.
if(!is.null(printing) & !is.null(layout$timestamp.x) & !is.null(layout$timestamp.y) & !is.null(layout$timestamp.size)){
graphics::text(layout$timestamp.x, layout$timestamp.y, paste0("Page ", p, printing, " ", Sys.Date()), adj = c(0, 0), cex = layout$timestamp.size, srt = -90)
}
}
}else{
pages = split.vector(ids, n = length(layout$label.x))
grDevices::pdf(file = paste0(tools::file_path_sans_ext(file), printing, ".pdf"), width = layout$page.width, height = layout$page.height)
graphics::par(mar = c(0, 0, 0, 0))
for(p in seq_along(pages)){
n = 1
plot(0, xlim=c(0, layout$page.width), ylim=c(layout$page.height, 0), ann=F, bty="n", type="n", xaxt = "n", yaxt = "n", xaxs = "i", yaxs = "i")
for(x in layout$label.x){
text = pages[[p]][n]
for(yi in seq_along(layout$label.y)){
y = layout$label.y[yi]
graphics::text(x, y, text, adj = c(0.5, NA), cex = layout$text.size, font = layout$text.font)
graphics::text(x, y, as.character(sublabel[yi]), adj = c(0.5, layout$sublabel.offset), cex = layout$sublabel.size, font = layout$sublabel.font)
}
n = n + 1
}
# Add vertical date and sheet stamp.
if(!is.null(printing) & !is.null(layout$timestamp.x) & !is.null(layout$timestamp.y) & !is.null(layout$timestamp.size)){
graphics::text(layout$timestamp.x, layout$timestamp.y, paste0("Page ", p, printing, " ", Sys.Date()), adj = c(0, 0), cex = layout$timestamp.size, srt = -90)
}
}
}
grDevices::dev.off()
}
##########
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.