Major Changes: - NEW: Scripts 09 & 10 for KPI calculation and enhanced reporting - NEW: Shell script wrappers (01-10) for easier execution - NEW: R packages flextable and officer for enhanced Word reports - NEW: DEPLOYMENT_README.md with complete deployment guide - RENAMED: Numbered R scripts (02, 03, 04) for clarity - REMOVED: Old package management scripts (using renv only) - UPDATED: Workflow now uses scripts 09->10 instead of 05 Files Changed: 90+ files New Packages: flextable, officer New Scripts: 09_run_calculate_kpis.sh, 10_run_kpi_report.sh Documentation: DEPLOYMENT_README.md, EMAIL_TO_ADMIN.txt See DEPLOYMENT_README.md for full deployment instructions.
513 lines
20 KiB
R
513 lines
20 KiB
R
message("No project_dir provided. Using default:", project_dir)
|
|
}
|
|
# Make project_dir available globally so parameters_project.R can use it
|
|
assign("project_dir", project_dir, envir = .GlobalEnv)
|
|
# Initialize project configuration and load utility functions
|
|
tryCatch({
|
|
source("parameters_project.R")
|
|
source("growth_model_utils.R")
|
|
}, error = function(e) {
|
|
warning("Default source files not found. Attempting to source from 'r_app' directory.")
|
|
tryCatch({
|
|
source(here::here("r_app", "parameters_project.R"))
|
|
source(here::here("r_app", "growth_model_utils.R"))
|
|
warning(paste("Successfully sourced files from 'r_app' directory."))
|
|
}, error = function(e) {
|
|
stop("Failed to source required files from both default and 'r_app' directories.")
|
|
})
|
|
})
|
|
log_message("Starting CI growth model interpolation")
|
|
# Load and process the data
|
|
tryCatch({
|
|
# Load the combined CI data
|
|
CI_data <- load_combined_ci_data(cumulative_CI_vals_dir)
|
|
# Validate harvesting data
|
|
if (is.null(harvesting_data) || nrow(harvesting_data) == 0) {
|
|
stop("No harvesting data available")
|
|
}
|
|
# Get the years from harvesting data
|
|
years <- harvesting_data %>%
|
|
filter(!is.na(season_start)) %>%
|
|
distinct(year) %>%
|
|
pull(year)
|
|
log_message(paste("Processing data for years:", paste(years, collapse = ", ")))
|
|
# Generate interpolated CI data for each year and field
|
|
CI_all <- generate_interpolated_ci_data(years, harvesting_data, CI_data)
|
|
# Calculate growth metrics and save the results
|
|
if (nrow(CI_all) > 0) {
|
|
# Add daily and cumulative metrics
|
|
CI_all_with_metrics <- calculate_growth_metrics(CI_all)
|
|
# Save the processed data
|
|
save_growth_model(
|
|
CI_all_with_metrics,
|
|
cumulative_CI_vals_dir,
|
|
"All_pivots_Cumulative_CI_quadrant_year_v2.rds"
|
|
)
|
|
} else {
|
|
log_message("No CI data was generated after interpolation", level = "WARNING")
|
|
}
|
|
log_message("Growth model interpolation completed successfully")
|
|
}, error = function(e) {
|
|
log_message(paste("Error in growth model interpolation:", e$message), level = "ERROR")
|
|
stop(e$message)
|
|
})
|
|
View(CI_all_with_metrics)
|
|
View(CI_data)
|
|
# Get the years from harvesting data
|
|
years <- harvesting_data %>%
|
|
filter(!is.na(season_start)) %>%
|
|
distinct(year) %>%
|
|
pull(year)
|
|
years
|
|
View(CI_all)
|
|
View(CI_all_with_metrics)
|
|
years
|
|
harvesting_data
|
|
ci_data
|
|
ci_data = CI_data
|
|
# Process each year
|
|
result <- purrr::map_df(years, function(yr) {
|
|
safe_log(paste("Processing year:", yr))
|
|
# Get the fields harvested in this year with valid season start dates
|
|
sub_fields <- harvesting_data %>%
|
|
dplyr::filter(year == yr, !is.na(season_start)) %>%
|
|
dplyr::pull(sub_field)
|
|
if (length(sub_fields) == 0) {
|
|
safe_log(paste("No fields with valid season data for year:", yr), "WARNING")
|
|
return(data.frame())
|
|
}
|
|
# Filter sub_fields to only include those with value data in ci_data
|
|
valid_sub_fields <- sub_fields %>%
|
|
purrr::keep(~ any(ci_data$sub_field == .x))
|
|
if (length(valid_sub_fields) == 0) {
|
|
safe_log(paste("No fields with CI data for year:", yr), "WARNING")
|
|
return(data.frame())
|
|
}
|
|
# Extract and interpolate data for each valid field
|
|
safe_log(paste("Processing", length(valid_sub_fields), "fields for year:", yr))
|
|
result <- purrr::map(valid_sub_fields, ~ extract_CI_data(.x,
|
|
harvesting_data = harvesting_data,
|
|
field_CI_data = ci_data,
|
|
season = yr)) %>%
|
|
purrr::list_rbind()
|
|
safe_log(paste("Generated", nrow(result), "interpolated data points for year:", yr))
|
|
return(result)
|
|
})
|
|
CI_all_with_metrics
|
|
CI_all <- CI_all %>%
|
|
group_by(Date, field, season) %>%
|
|
filter(!(field == "00F25" & season == 2023 & duplicated(DOY)))
|
|
View(CI_all)
|
|
# Add daily and cumulative metrics
|
|
CI_all_with_metrics <- calculate_growth_metrics(CI_all)
|
|
# Save the processed data
|
|
save_growth_model(
|
|
CI_all_with_metrics,
|
|
cumulative_CI_vals_dir,
|
|
"All_pivots_Cumulative_CI_quadrant_year_v2.rds"
|
|
)
|
|
# Set up basic report parameters from input values
|
|
report_date <- params$report_date
|
|
mail_day <- params$mail_day
|
|
borders <- params$borders
|
|
ci_plot_type <- params$ci_plot_type
|
|
colorblind_friendly <- params$colorblind_friendly
|
|
facet_by_season <- params$facet_by_season
|
|
x_axis_unit <- params$x_axis_unit
|
|
# Configure knitr options
|
|
knitr::opts_chunk$set(warning = FALSE, message = FALSE)
|
|
# Load all packages at once with suppressPackageStartupMessages
|
|
suppressPackageStartupMessages({
|
|
library(here)
|
|
library(sf)
|
|
library(terra)
|
|
library(exactextractr)
|
|
library(tidyverse)
|
|
library(tmap)
|
|
library(lubridate)
|
|
library(zoo)
|
|
library(rsample)
|
|
library(caret)
|
|
library(randomForest)
|
|
library(CAST)
|
|
library(knitr)
|
|
library(tidyr)
|
|
})
|
|
# Load custom utility functions
|
|
tryCatch({
|
|
source("report_utils.R")
|
|
}, error = function(e) {
|
|
message(paste("Error loading report_utils.R:", e$message))
|
|
# Try alternative path if the first one fails
|
|
tryCatch({
|
|
source(here::here("r_app", "report_utils.R"))
|
|
}, error = function(e) {
|
|
stop("Could not load report_utils.R from either location: ", e$message)
|
|
})
|
|
})
|
|
# Set the project directory from parameters
|
|
project_dir <- params$data_dir
|
|
# Source project parameters with error handling
|
|
tryCatch({
|
|
source(here::here("r_app", "parameters_project.R"))
|
|
}, error = function(e) {
|
|
stop("Error loading parameters_project.R: ", e$message)
|
|
})
|
|
# Log initial configuration
|
|
safe_log("Starting the R Markdown script with KPIs")
|
|
safe_log(paste("mail_day params:", params$mail_day))
|
|
safe_log(paste("report_date params:", params$report_date))
|
|
safe_log(paste("mail_day variable:", mail_day))
|
|
## SIMPLE KPI LOADING - robust lookup with fallbacks
|
|
# Primary expected directory inside the laravel storage
|
|
kpi_data_dir <- file.path("laravel_app", "storage", "app", project_dir, "reports", "kpis")
|
|
date_suffix <- format(as.Date(report_date), "%Y%m%d")
|
|
# Candidate filenames we expect (exact and common variants)
|
|
expected_summary_names <- c(
|
|
paste0(project_dir, "_kpi_summary_tables_", date_suffix, ".rds"),
|
|
paste0(project_dir, "_kpi_summary_tables.rds"),
|
|
"kpi_summary_tables.rds",
|
|
paste0("kpi_summary_tables_", date_suffix, ".rds")
|
|
)
|
|
expected_field_details_names <- c(
|
|
paste0(project_dir, "_field_details_", date_suffix, ".rds"),
|
|
paste0(project_dir, "_field_details.rds"),
|
|
"field_details.rds"
|
|
)
|
|
# Helper to attempt loading a file from the directory or fallback to a workspace-wide search
|
|
try_load_from_dir <- function(dir, candidates) {
|
|
if (!dir.exists(dir)) return(NULL)
|
|
for (name in candidates) {
|
|
f <- file.path(dir, name)
|
|
if (file.exists(f)) return(f)
|
|
}
|
|
return(NULL)
|
|
}
|
|
# Try primary directory first
|
|
summary_file <- try_load_from_dir(kpi_data_dir, expected_summary_names)
|
|
field_details_file <- try_load_from_dir(kpi_data_dir, expected_field_details_names)
|
|
# If not found, perform a workspace-wide search (slower) limited to laravel_app storage
|
|
if (is.null(summary_file) || is.null(field_details_file)) {
|
|
safe_log(paste("KPI files not found in", kpi_data_dir, "—searching workspace for RDS files"))
|
|
# List rds files under laravel_app/storage/app recursively
|
|
files <- list.files(path = file.path("laravel_app", "storage", "app"), pattern = "\\.rds$", recursive = TRUE, full.names = TRUE)
|
|
# Try to match by expected names
|
|
if (is.null(summary_file)) {
|
|
matched <- files[basename(files) %in% expected_summary_names]
|
|
if (length(matched) > 0) summary_file <- matched[1]
|
|
}
|
|
if (is.null(field_details_file)) {
|
|
matched2 <- files[basename(files) %in% expected_field_details_names]
|
|
if (length(matched2) > 0) field_details_file <- matched2[1]
|
|
}
|
|
}
|
|
# Final checks and load with safe error messages
|
|
kpi_files_exist <- FALSE
|
|
if (!is.null(summary_file) && file.exists(summary_file)) {
|
|
safe_log(paste("Loading KPI summary from:", summary_file))
|
|
summary_tables <- tryCatch(readRDS(summary_file), error = function(e) { safe_log(paste("Failed to read summary RDS:", e$message), "ERROR"); NULL })
|
|
if (!is.null(summary_tables)) kpi_files_exist <- TRUE
|
|
} else {
|
|
safe_log(paste("KPI summary file not found. Searched:", paste(expected_summary_names, collapse=", ")), "WARNING")
|
|
}
|
|
if (!is.null(field_details_file) && file.exists(field_details_file)) {
|
|
safe_log(paste("Loading field details from:", field_details_file))
|
|
field_details_table <- tryCatch(readRDS(field_details_file), error = function(e) { safe_log(paste("Failed to read field details RDS:", e$message), "ERROR"); NULL })
|
|
if (!is.null(field_details_table)) kpi_files_exist <- kpi_files_exist && TRUE
|
|
} else {
|
|
safe_log(paste("Field details file not found. Searched:", paste(expected_field_details_names, collapse=", ")), "WARNING")
|
|
}
|
|
if (kpi_files_exist) {
|
|
safe_log("✓ KPI summary tables loaded successfully")
|
|
} else {
|
|
safe_log("KPI files could not be located or loaded. KPI sections will be skipped.", "WARNING")
|
|
}
|
|
# Set locale for consistent date formatting
|
|
Sys.setlocale("LC_TIME", "C")
|
|
# Initialize date variables from parameters
|
|
today <- as.character(report_date)
|
|
mail_day_as_character <- as.character(mail_day)
|
|
# Calculate report dates and weeks
|
|
report_date_obj <- as.Date(today)
|
|
current_week <- as.numeric(format(report_date_obj, "%U"))
|
|
year <- as.numeric(format(report_date_obj, "%Y"))
|
|
# Calculate dates for weekly analysis
|
|
week_start <- report_date_obj - ((as.numeric(format(report_date_obj, "%w")) + 1) %% 7)
|
|
week_end <- week_start + 6
|
|
# Calculate week days (copied from 05 script for compatibility)
|
|
report_date_as_week_day <- weekdays(lubridate::ymd(today))
|
|
days_of_week <- c("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
|
|
# Calculate initial week number
|
|
week <- lubridate::week(today) - 1
|
|
safe_log(paste("Initial week calculation:", week, "today:", today))
|
|
# Calculate previous dates for comparisons
|
|
today_minus_1 <- as.character(lubridate::ymd(today) - 7)
|
|
today_minus_2 <- as.character(lubridate::ymd(today) - 14)
|
|
today_minus_3 <- as.character(lubridate::ymd(today) - 21)
|
|
# Adjust week calculation based on mail day
|
|
if (which(days_of_week == report_date_as_week_day) > which(days_of_week == mail_day_as_character)) {
|
|
safe_log("Adjusting weeks because of mail day")
|
|
week <- lubridate::week(today) + 1
|
|
today_minus_1 <- as.character(lubridate::ymd(today))
|
|
today_minus_2 <- as.character(lubridate::ymd(today) - 7)
|
|
today_minus_3 <- as.character(lubridate::ymd(today) - 14)
|
|
}
|
|
# Calculate week numbers for previous weeks
|
|
week_minus_1 <- week - 1
|
|
week_minus_2 <- week - 2
|
|
week_minus_3 <- week - 3
|
|
# Format current week with leading zeros
|
|
week <- sprintf("%02d", week)
|
|
safe_log(paste("Report week:", current_week, "Year:", year))
|
|
safe_log(paste("Week range:", week_start, "to", week_end))
|
|
## SIMPLE KPI LOADING - robust lookup with fallbacks
|
|
# Primary expected directory inside the laravel storage
|
|
kpi_data_dir <- file.path("laravel_app", "storage", "app", project_dir, "reports", "kpis")
|
|
date_suffix <- format(as.Date(report_date), "%Y%m%d")
|
|
# Candidate filenames we expect (exact and common variants)
|
|
expected_summary_names <- c(
|
|
paste0(project_dir, "_kpi_summary_tables_", date_suffix, ".rds"),
|
|
paste0(project_dir, "_kpi_summary_tables.rds"),
|
|
"kpi_summary_tables.rds",
|
|
paste0("kpi_summary_tables_", date_suffix, ".rds")
|
|
)
|
|
expected_field_details_names <- c(
|
|
paste0(project_dir, "_field_details_", date_suffix, ".rds"),
|
|
paste0(project_dir, "_field_details.rds"),
|
|
"field_details.rds"
|
|
)
|
|
# Helper to attempt loading a file from the directory or fallback to a workspace-wide search
|
|
try_load_from_dir <- function(dir, candidates) {
|
|
if (!dir.exists(dir)) return(NULL)
|
|
for (name in candidates) {
|
|
f <- file.path(dir, name)
|
|
if (file.exists(f)) return(f)
|
|
}
|
|
return(NULL)
|
|
}
|
|
# Try primary directory first
|
|
summary_file <- try_load_from_dir(kpi_data_dir, expected_summary_names)
|
|
field_details_file <- try_load_from_dir(kpi_data_dir, expected_field_details_names)
|
|
# If not found, perform a workspace-wide search (slower) limited to laravel_app storage
|
|
if (is.null(summary_file) || is.null(field_details_file)) {
|
|
safe_log(paste("KPI files not found in", kpi_data_dir, "—searching workspace for RDS files"))
|
|
# List rds files under laravel_app/storage/app recursively
|
|
files <- list.files(path = file.path("laravel_app", "storage", "app"), pattern = "\\.rds$", recursive = TRUE, full.names = TRUE)
|
|
# Try to match by expected names
|
|
if (is.null(summary_file)) {
|
|
matched <- files[basename(files) %in% expected_summary_names]
|
|
if (length(matched) > 0) summary_file <- matched[1]
|
|
}
|
|
if (is.null(field_details_file)) {
|
|
matched2 <- files[basename(files) %in% expected_field_details_names]
|
|
if (length(matched2) > 0) field_details_file <- matched2[1]
|
|
}
|
|
}
|
|
# Final checks and load with safe error messages
|
|
kpi_files_exist <- FALSE
|
|
if (!is.null(summary_file) && file.exists(summary_file)) {
|
|
safe_log(paste("Loading KPI summary from:", summary_file))
|
|
summary_tables <- tryCatch(readRDS(summary_file), error = function(e) { safe_log(paste("Failed to read summary RDS:", e$message), "ERROR"); NULL })
|
|
if (!is.null(summary_tables)) kpi_files_exist <- TRUE
|
|
} else {
|
|
safe_log(paste("KPI summary file not found. Searched:", paste(expected_summary_names, collapse=", ")), "WARNING")
|
|
}
|
|
if (!is.null(field_details_file) && file.exists(field_details_file)) {
|
|
safe_log(paste("Loading field details from:", field_details_file))
|
|
field_details_table <- tryCatch(readRDS(field_details_file), error = function(e) { safe_log(paste("Failed to read field details RDS:", e$message), "ERROR"); NULL })
|
|
if (!is.null(field_details_table)) kpi_files_exist <- kpi_files_exist && TRUE
|
|
} else {
|
|
safe_log(paste("Field details file not found. Searched:", paste(expected_field_details_names, collapse=", ")), "WARNING")
|
|
}
|
|
if (kpi_files_exist) {
|
|
safe_log("✓ KPI summary tables loaded successfully")
|
|
} else {
|
|
safe_log("KPI files could not be located or loaded. KPI sections will be skipped.", "WARNING")
|
|
}
|
|
## SIMPLE KPI LOADING - robust lookup with fallbacks
|
|
# Primary expected directory inside the laravel storage
|
|
kpi_data_dir <- file.path("laravel_app", "storage", "app", project_dir, "reports", "kpis")
|
|
kpi_data_dir
|
|
kpi_data_dir
|
|
## SIMPLE KPI LOADING - robust lookup with fallbacks
|
|
# Primary expected directory inside the laravel storage
|
|
kpi_data_dir <- file.path(here("laravel_app", "storage", "app", project_dir, "reports", "kpis"))
|
|
kpi_data_dir
|
|
# Candidate filenames we expect (exact and common variants)
|
|
expected_summary_names <- c(
|
|
paste0(project_dir, "_kpi_summary_tables_", date_suffix, ".rds"),
|
|
paste0(project_dir, "_kpi_summary_tables.rds"),
|
|
"kpi_summary_tables.rds",
|
|
paste0("kpi_summary_tables_", date_suffix, ".rds")
|
|
)
|
|
expected_field_details_names <- c(
|
|
paste0(project_dir, "_field_details_", date_suffix, ".rds"),
|
|
paste0(project_dir, "_field_details.rds"),
|
|
"field_details.rds"
|
|
)
|
|
# Helper to attempt loading a file from the directory or fallback to a workspace-wide search
|
|
try_load_from_dir <- function(dir, candidates) {
|
|
if (!dir.exists(dir)) return(NULL)
|
|
for (name in candidates) {
|
|
f <- file.path(dir, name)
|
|
if (file.exists(f)) return(f)
|
|
}
|
|
return(NULL)
|
|
}
|
|
# Try primary directory first
|
|
summary_file <- try_load_from_dir(kpi_data_dir, expected_summary_names)
|
|
field_details_file <- try_load_from_dir(kpi_data_dir, expected_field_details_names)
|
|
# If not found, perform a workspace-wide search (slower) limited to laravel_app storage
|
|
if (is.null(summary_file) || is.null(field_details_file)) {
|
|
safe_log(paste("KPI files not found in", kpi_data_dir, "—searching workspace for RDS files"))
|
|
# List rds files under laravel_app/storage/app recursively
|
|
files <- list.files(path = file.path("laravel_app", "storage", "app"), pattern = "\\.rds$", recursive = TRUE, full.names = TRUE)
|
|
# Try to match by expected names
|
|
if (is.null(summary_file)) {
|
|
matched <- files[basename(files) %in% expected_summary_names]
|
|
if (length(matched) > 0) summary_file <- matched[1]
|
|
}
|
|
if (is.null(field_details_file)) {
|
|
matched2 <- files[basename(files) %in% expected_field_details_names]
|
|
if (length(matched2) > 0) field_details_file <- matched2[1]
|
|
}
|
|
}
|
|
# Final checks and load with safe error messages
|
|
kpi_files_exist <- FALSE
|
|
if (!is.null(summary_file) && file.exists(summary_file)) {
|
|
safe_log(paste("Loading KPI summary from:", summary_file))
|
|
summary_tables <- tryCatch(readRDS(summary_file), error = function(e) { safe_log(paste("Failed to read summary RDS:", e$message), "ERROR"); NULL })
|
|
if (!is.null(summary_tables)) kpi_files_exist <- TRUE
|
|
} else {
|
|
safe_log(paste("KPI summary file not found. Searched:", paste(expected_summary_names, collapse=", ")), "WARNING")
|
|
}
|
|
summary_file
|
|
kpi_data_dir
|
|
library(officer)
|
|
library(flextable)
|
|
# Data setup
|
|
summary_tables <- list()
|
|
summary_tables$field_uniformity_summary <- data.frame(
|
|
"Uniformity Level" = c("Excellent", "Good", "Poor"),
|
|
"Count" = c(15, 8, 3),
|
|
"Percent" = c("62.5%", "33.3%", "12.5%")
|
|
)
|
|
summary_tables$weed_presence_summary <- data.frame(
|
|
"Weed Risk Level" = c("Low", "Moderate", "High"),
|
|
"Field Count" = c(18, 6, 2),
|
|
"Percent" = c("75.0%", "25.0%", "8.3%")
|
|
)
|
|
doc <- read_docx()
|
|
doc <- body_add_par(doc, "KPI Grid Test Report", style = "heading 1")
|
|
doc <- body_add_par(doc, "Executive Summary - Key Performance Indicators", style = "heading 2")
|
|
doc <- body_add_par(doc, "This section demonstrates just two KPI tables side by side.", style = "Normal")
|
|
doc <- body_add_section(doc, prop_section(
|
|
section_type = "continuous",
|
|
columns = columns(widths = c(4.25, 4.25))
|
|
))
|
|
doc <- body_add_flextable(doc, flextable(summary_tables$field_uniformity_summary) %>% set_caption("Field Uniformity Summary"))
|
|
doc <- body_add_break(doc, "column")
|
|
doc <- body_add_flextable(doc, flextable(summary_tables$weed_presence_summary) %>% set_caption("Weed Presence Score Summary"))
|
|
doc <- body_add_section(doc, prop_section(
|
|
section_type = "continuous",
|
|
columns = columns(widths = c(8.5))
|
|
))
|
|
doc <- body_add_par(doc, "This is a test report to verify the KPI grid layout.", style = "Normal")
|
|
print(doc, target = "tables_side_by_side.docx")
|
|
here()
|
|
getwd()
|
|
print(doc, target = "tables_side_by_side.docx")
|
|
doc
|
|
print(doc, target = "tables_side_by_side.docx")
|
|
print(doc, target = "r_app/tables_side_by_side.docx")
|
|
library(officer)
|
|
library(flextable)
|
|
# Create example data
|
|
summary_tables <- list()
|
|
summary_tables$field_uniformity_summary <- data.frame(
|
|
"Uniformity Level" = c("Excellent", "Good", "Poor"),
|
|
"Count" = c(15, 8, 3),
|
|
"Percent" = c("62.5%", "33.3%", "12.5%")
|
|
)
|
|
summary_tables$weed_presence_summary <- data.frame(
|
|
"Weed Risk Level" = c("Low", "Moderate", "High"),
|
|
"Field Count" = c(18, 6, 2),
|
|
"Percent" = c("75.0%", "25.0%", "8.3%")
|
|
)
|
|
# Create document
|
|
doc <- read_docx()
|
|
doc <- body_add_par(doc, "KPI Grid Test Report", style = "heading 1")
|
|
doc <- body_add_par(doc, "Executive Summary - Key Performance Indicators", style = "heading 2")
|
|
doc <- body_add_par(doc, "This section demonstrates just two KPI tables side by side.", style = "Normal")
|
|
# Two-column section
|
|
doc <- body_add_section(doc, prop_section(
|
|
section_type = "continuous",
|
|
columns = columns(widths = c(4.25, 4.25))
|
|
))
|
|
library(officer)
|
|
library(flextable)
|
|
# Create example data
|
|
summary_tables <- list()
|
|
summary_tables$field_uniformity_summary <- data.frame(
|
|
"Uniformity Level" = c("Excellent", "Good", "Poor"),
|
|
"Count" = c(15, 8, 3),
|
|
"Percent" = c("62.5%", "33.3%", "12.5%")
|
|
)
|
|
summary_tables$weed_presence_summary <- data.frame(
|
|
"Weed Risk Level" = c("Low", "Moderate", "High"),
|
|
"Field Count" = c(18, 6, 2),
|
|
"Percent" = c("75.0%", "25.0%", "8.3%")
|
|
)
|
|
# Create document
|
|
doc <- read_docx()
|
|
doc <- body_add_par(doc, "KPI Grid Test Report", style = "heading 1")
|
|
doc <- body_add_par(doc, "Executive Summary - Key Performance Indicators", style = "heading 2")
|
|
doc <- body_add_par(doc, "This section demonstrates just two KPI tables side by side.", style = "Normal")
|
|
# Two-column section
|
|
doc <- body_add_section(doc, prop_section(
|
|
section_type = "continuous",
|
|
columns = columns(widths = c(4.25, 4.25))
|
|
))
|
|
packageVersion("officer")
|
|
??body_add_section
|
|
library(officer)
|
|
?body_add_section
|
|
library(officer)
|
|
library(flextable)
|
|
# Create example data
|
|
ft1 <- flextable(data.frame(
|
|
"Uniformity Level" = c("Excellent", "Good", "Poor"),
|
|
"Count" = c(15, 8, 3),
|
|
"Percent" = c("62.5%", "33.3%", "12.5%")
|
|
)) %>% set_caption("Field Uniformity Summary")
|
|
ft2 <- flextable(data.frame(
|
|
"Weed Risk Level" = c("Low", "Moderate", "High"),
|
|
"Field Count" = c(18, 6, 2),
|
|
"Percent" = c("75.0%", "25.0%", "8.3%")
|
|
)) %>% set_caption("Weed Presence Score Summary")
|
|
doc <- read_docx()
|
|
doc <- body_add_par(doc, "KPI Grid Test Report", style = "heading 1")
|
|
library(dplyr)
|
|
# Create example data
|
|
ft1 <- flextable(data.frame(
|
|
"Uniformity Level" = c("Excellent", "Good", "Poor"),
|
|
"Count" = c(15, 8, 3),
|
|
"Percent" = c("62.5%", "33.3%", "12.5%")
|
|
)) %>% set_caption("Field Uniformity Summary")
|
|
ft2 <- flextable(data.frame(
|
|
"Weed Risk Level" = c("Low", "Moderate", "High"),
|
|
"Field Count" = c(18, 6, 2),
|
|
"Percent" = c("75.0%", "25.0%", "8.3%")
|
|
)) %>% set_caption("Weed Presence Score Summary")
|
|
doc <- read_docx()
|
|
doc <- body_add_par(doc, "KPI Grid Test Report", style = "heading 1")
|
|
doc <- body_add_par(doc, "Executive Summary - Key Performance Indicators", style = "heading 2")
|
|
doc <- body_add_par(doc, "This section demonstrates two KPI tables side by side.", style = "Normal")
|
|
# Create a Word table (1 row, 2 columns)
|
|
doc <- body_add_table(doc, value = data.frame(A = "", B = ""), style = "Table Grid")
|
|
# Move cursor to first cell, insert first flextable
|
|
doc <- cursor_forward(doc)
|
|
doc <- slip_in_flextable(doc, ft1, pos = "on")
|
|
# Move cursor to second cell, insert second flextable
|
|
doc <- cursor_forward(doc)
|