---
title: "Table: A Step-by-Step Guide"
author: "Pattawee Puangchit"
date: "`r Sys.Date()`"
output:
  html_document:
    toc: true
    toc_float:
      collapsed: true
      smooth_scroll: true
    css: mystyle.css
    number_sections: true
    code_folding: show
    self_contained: false
vignette: >
  %\VignetteIndexEntry{Table: A Step-by-Step Guide}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE, eval = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  warning = FALSE,
  message = FALSE,
  eval = requireNamespace("GTAPViz", quietly = TRUE)
)
```


```{r Dev Period, include = FALSE, eval = TRUE}
devtools::load_all()
try(devtools::load_all(".."), silent = TRUE)  # go up one level from /vignettes/

input_path <- system.file("extdata/in", package = "GTAPViz")
sl4.plot.data <- readRDS(file.path(input_path, "sl4.plot.data.rds"))
har.plot.data <- readRDS(file.path(input_path, "har.plot.data.rds"))
macro.data    <- readRDS(file.path(input_path, "macro.data.rds"))
```

This vignette illustrates how to set up table configurations and generate outputs.  
For a complete list of available tables with sample images, see the [table catalog](https://pattawee.shinyapps.io/gtapviz-advanced-table-configs/).

# Structured Table 

This is an example of how to create a structured pivot table suitable for inclusion in academic presentations.

<div class="info-box">
<strong>Important:</strong> <br>
The `report_table` function requires **a data list**—not a data frame. 

- This list structure matches the format of `sl4.plot.data` or `har.plot.data`, without delisting individual elements.

- This differs from the plotting functions, which use a **data frame** as input.

- Multiple tables can be generated in a single setup using a data list.  
  For example, you can generate report tables for **all data frames within `sl4.plot.data`** in one code block.
</div>

```{r Comparison Table, eval = FALSE}
report_table(
  data_list = sl4.plot.data,
  pivot_col = list(REG = "Variable",
                   'COMM*REG' = "Commodity"),
  group_by =  list(
    REG = c("Experiment", "Region"),
    'COMM*REG' = c("Experiment", "Region")),
  rename_cols = list("Experiment" = "Scenario"),

  total_column = FALSE,
  decimal = 4,
  subtotal_level = FALSE,
  repeat_label = FALSE,
  include_units = TRUE,

  var_name_by_description = TRUE,
  add_var_info = TRUE,
  add_group_line = FALSE,
  
  separate_sheet_by = "Unit",
  export_table = FALSE,
  output_path = NULL,
  separate_file = FALSE,
  workbook_name = "Comparison Table"
)
```

<details>
  <summary class="toggle-summary">💡 Tip</summary>
  
<div class="tip-box">
`var_name_by_description` replaces variable names with their full descriptions to enhance clarity and give the output a more academic appearance.
</div>

</details>

# Decomposition Table {#sec:decomp-table}

The same `report_table` function can be used to generate decomposition tables, including a total column, as shown in the example below:

```{r Decomposition Table, eval = FALSE}
report_table(
  data_list = har.plot.data,
  pivot_col = list(A = "COLUMN", 
                   E1 = "PRICES"),
  group_by = list(
    A = list("Experiment", "Region"), 
    E1 = list("Experiment", "Commodity", "PRICES")
  ),
  rename_cols = list("Experiment" = "Scenario"),
  
  total_column = TRUE,
  decimal = 6,
  subtotal_level = FALSE,
  repeat_label = FALSE,
  include_units = TRUE,

  var_name_by_description = FALSE,
  add_var_info = FALSE,
  add_group_line = FALSE,

  separate_sheet_by = "Region",
  export_table = FALSE,
  output_path = NULL,
  separate_file = FALSE,
  workbook_name = "Decomposition Table"
)
```


# Interactive Pivot Tables {#sec:pivot-table}

Unlike static tables generated by `report_table()`, pivot tables remain fully interactive in the Excel output. However, they work with **a single data frame** at a time (just like the plotting functions).

This function offers:

- **Comprehensive Filtering**  
  Add multiple filtering dimensions to enhance flexibility and enable users to explore the data from different perspectives.

- **Retention of Raw Data**  
  The raw dataset is included in the Excel file, allowing downstream users—especially in Excel—to reconstruct or customize pivot tables as needed.

- **User-Oriented Design**  
  Ideal for sharing with non-R users, the output is organized for intuitive exploration and ease of use.


```{r Pivot Table with Filter, eval=FALSE}
pivot_table_with_filter(
  data = sl4.plot.data[["COMM*REG"]],
  filter = c("Variable", "Unit"),    # Allow filtering by variable type and unit
  rows = c("Region", "Commodity"),      # Regions and sectors as row fields
  cols = c("Experiment"),            # Experiments as column fields
  data_fields = "Value",             # Values to be aggregated
  raw_sheet_name = "Raw_Data",       # Sheet name for raw data
  pivot_sheet_name = "Sector_Pivot", # Sheet name for pivot table
  export_table = FALSE,
  output_path = NULL,
  workbook_name = "Sectoral_Impact_Analysis.xlsx"
)
```


# Sample Data

Sample data used in this vignette is obtained from the GTAPv7 model
and utilizes data from the GTAP 11 database. For
more details, refer to the [GTAP Database Archive](https://www.gtap.agecon.purdue.edu/databases/archives.asp).


```{=html}
<script>
window.addEventListener("load", function () {
  document.querySelectorAll("pre code").forEach(function (codeBlock) {
    const button = document.createElement("button");
    button.className = "copy-code-button";
    button.type = "button";
    button.innerText = "Copy";
    button.style.position = "absolute";
    button.style.top = "4px";
    button.style.right = "4px";

    button.addEventListener("click", () => {
      navigator.clipboard.writeText(codeBlock.innerText).then(() => {
        button.innerText = "Copied!";
        setTimeout(() => (button.innerText = "Copy"), 1500);
      });
    });

    const pre = codeBlock.parentNode;
    pre.style.position = "relative";
    pre.insertBefore(button, codeBlock);
  });
});
</script>

<script>
document.addEventListener("DOMContentLoaded", function () {
  let prevScrollPos = window.pageYOffset;
  const navbar = document.querySelector(".navbar");

  window.addEventListener("scroll", function () {
    const currentScrollPos = window.pageYOffset;
    if (prevScrollPos > currentScrollPos) {
      // Scrolling up
      navbar.style.top = "0";
    } else {
      // Scrolling down
      navbar.style.top = "-70px";
    }
    prevScrollPos = currentScrollPos;
  });
});
</script>
```