Skip to content

Commit 07773f2

Browse files
authored
Merge pull request #22 from Swechhya/auto-column-type
Add column type mapping
2 parents 7272b29 + 7f8b71f commit 07773f2

File tree

7 files changed

+178
-8
lines changed

7 files changed

+178
-8
lines changed

R/get_col_types.R

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Get column types of the given data
2+
get_col_types <- function(data) {
3+
4+
if(is.data.frame(data)){
5+
6+
colTypes <- as.character(lapply(data,class))
7+
8+
}else if(is.matrix(data)){
9+
10+
colTypes <- rep(typeof(data), ncol(data))
11+
12+
}else {
13+
14+
stop("'data' must be either a matrix or a data frame, cannot be ",
15+
class(data))
16+
}
17+
mappedColTypes <- sapply(colTypes, function(colType){
18+
switch(colType,
19+
factor = "text",
20+
integer="integer",
21+
double="numeric",
22+
logical="checkbox",
23+
Date="calendar",
24+
numeric="numeric",
25+
"text")
26+
})
27+
28+
as.character(mappedColTypes)
29+
}

R/jexcel.R

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454
#' @param loadingSpin a boolean value indicating if loading spinner should be enabled. By default it is set to false.
5555
#' @param style a named list to specify style for each cell. The name should be the cell address and the value should be
5656
#' a valid 'css' string with styles. For example, to style cell 'A1', the list should look like
57+
#' @param autoColTypes a boolean value indicating if column type should be automatically detected if
58+
#' 'type' is not specified in 'columns' attribute
5759
#' \code{style = list("A1" = "background-color: gray;")}.
5860
#' @import jsonlite
5961
#' @import htmlwidgets
@@ -86,7 +88,8 @@ excelTable <-
8688
fullscreen = FALSE,
8789
lazyLoading = FALSE,
8890
loadingSpin = FALSE,
89-
style = NULL) {
91+
style = NULL,
92+
autoColTypes = TRUE) {
9093
# List of parameters to send to js
9194
paramList <- list()
9295

@@ -137,8 +140,7 @@ excelTable <-
137140
paramList$colHeaders <- jsonlite::toJSON(colHeaders)
138141

139142

140-
} else if (!is.null(columns))
141-
{
143+
} else if (!is.null(columns)) {
142144
#Check if 'columns' is a dataframe
143145
if (!is.data.frame(columns)) {
144146
stop("'columns' must be a dataframe, cannot be ", class(columns))
@@ -189,6 +191,29 @@ excelTable <-
189191

190192
}
191193

194+
#Check autoColTypes
195+
#If 'type' attribute is not specified in column and autoColTypes is true, then we map this and add it
196+
#column attributes
197+
if(autoColTypes && !is.null(data)){
198+
if(is.null(columns)){
199+
message("Since 'type' attribute is not specified and autoColTypes is true, detecting type from 'data'")
200+
201+
colTypes <- get_col_types(data)
202+
columns <- data.frame(type=colTypes)
203+
paramList$columns <- jsonlite::toJSON(columns)
204+
}else{
205+
if(!"type" %in% colnames(columns) && autoColTypes){
206+
message("Since 'type' attribute is not specified and autoColTypes is true, detecting type from 'data'")
207+
208+
colTypes <- get_col_types(data)
209+
columns$type <- colTypes
210+
paramList$columns <-
211+
jsonlite::toJSON(columns[colnames(columns) %in% colAttributes])
212+
}
213+
}
214+
}
215+
216+
192217
#Check row height
193218
if (!is.null(rowHeight)) {
194219
if (!is.data.frame(rowHeight) && !is.matrix(rowHeight)) {
@@ -210,7 +235,7 @@ excelTable <-
210235
if (!is.null(nestedHeaders)) {
211236
# nestedHeaders should be list
212237
if (!is.list(nestedHeaders)) {
213-
stop("'nestedHeaders' must be a list of dataframe(s), cannot be ",
238+
stop("'nestedHeaders' must be a list of dataframe(s), cannot be ",
214239
class(nestedHeaders))
215240
}
216241

inst/htmlwidgets/jexcel.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ HTMLWidgets.widget({
5252
}
5353

5454
excel = jexcel(container, otherParams);
55-
excel.updateSelectionFromCoords(selection[0], selection[1], selection[2], selection[3]);
55+
56+
if(selection){
57+
excel.updateSelectionFromCoords(selection[0], selection[1], selection[2], selection[3]);
58+
}
5659

5760
},
5861

@@ -72,7 +75,7 @@ HTMLWidgets.widget({
7275
},
7376

7477
onChangeHeader: function(obj, column, oldValue, newValue){
75-
debugger;
78+
7679
if (HTMLWidgets.shinyMode) {
7780
var newColHeader = this.colHeaders;
7881
newColHeader[parseInt(column)] = newValue;

man/excelTable.Rd

Lines changed: 5 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test_autoColType.R

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
context("'autoColType' argument")
2+
3+
test_that("'autoColType' returns null when data is null ", {
4+
5+
testthat::expect_null(excelTable()$x$autoColType)
6+
})
7+
8+
test_that("'autoColType' returns null when 'data' is not null and 'autoColType' is FALSE", {
9+
d <- matrix(1:100, ncol=10)
10+
testthat::expect_null(suppressWarnings(excelTable(data = d, autoColType = FALSE)$x$autoColType))
11+
})
12+
13+
test_that("'autoColType' returns null when 'data' is not null and 'type' attribute in column is specified", {
14+
data <- data.frame(Model = c('Mazda', 'Pegeout', 'Honda Fit', 'Honda CRV'),
15+
Date=c('2006-01-01', '2005-01-01','2004-01-01', '2003-01-01' ))
16+
17+
columns <- data.frame(title=c('Model', 'Date' ),
18+
width= c(300, 300),
19+
type=c('text', 'calendar'))
20+
testthat::expect_null(suppressWarnings(excelTable(data = data, columns=columns)$x$autoColType))
21+
})
22+
23+
test_that("'autoColType' returns valid values when 'data' is not null and 'type' attribute in columns is not specified", {
24+
data <- data.frame(Model = c('Mazda', 'Pegeout', 'Honda Fit', 'Honda CRV'),
25+
Date=c('TRUE', 'FALSE', 'TRUE', 'TRUE' ))
26+
27+
testthat::expect_s3_class(suppressWarnings(excelTable(data = data))$x$columns, "json")
28+
})
29+
30+
test_that("'type' attribute of 'columns' should return supplied value when 'data' is not null and 'type' attribute in columns is specified", {
31+
data <- data.frame(Model = c('Mazda', 'Pegeout', 'Honda Fit', 'Honda CRV'),
32+
Date=c('2006-01-01', '2005-01-01','2004-01-01', '2003-01-01' ),
33+
Availability = c(TRUE, FALSE, TRUE, TRUE))
34+
35+
columns <- data.frame(title=c('Model', 'Date', 'Availability'),
36+
width= c(300, 300, 300),
37+
type=c('text', 'calendar', 'checkbox'))
38+
testthat::expect_equal(jsonlite::fromJSON(suppressWarnings(excelTable(data = data, columns=columns))$x$columns)$type,
39+
c("text", "calendar", "checkbox"))
40+
})
41+
42+
test_that("'autoColType' returns valid values when 'data' is not null and 'type' attribute in columns is not specified", {
43+
data <- data.frame(Model = c('Mazda', 'Pegeout', 'Honda Fit', 'Honda CRV'),
44+
Date=c('TRUE', 'FALSE', 'TRUE', 'TRUE' ))
45+
46+
testthat::expect_message(suppressWarnings(excelTable(data = data)))
47+
})

tests/testthat/test_data.R

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,10 @@ test_that("valid 'data' object is passed to htmlwidget", {
99
d <- matrix(1:100, ncol=10)
1010
testthat::expect_s3_class(suppressWarnings(excelTable(data=d))$x$data, "json")
1111
})
12+
13+
test_that("valid 'data' object is passed to htmlwidget", {
14+
d <- data.frame(Model = c('Mazda', 'Pegeout', 'Honda Fit', 'Honda CRV'),
15+
Availability = c(TRUE, FALSE, TRUE, TRUE))
16+
testthat::expect_s3_class(suppressWarnings(excelTable(data=d))$x$data, "json")
17+
})
18+
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
context("get_col_types")
2+
3+
test_that("'get_col_types' argument gives error if 'data' not a dataframe or matrix", {
4+
d <- c(1:10)
5+
testthat::expect_error(get_col_types(data = d), c("'data' must be either a matrix or a data frame, cannot be integer"))
6+
})
7+
8+
test_that("'get_col_types' argument gives character if 'data' a dataframe or matrix", {
9+
d <- matrix(1:100, ncol=10)
10+
testthat::expect_equal(get_col_types(data=d), rep("integer", 10))
11+
})
12+
13+
test_that("'get_col_types' argument gives character if 'data' a dataframe or matrix", {
14+
d <- data.frame(Model = c('Mazda', 'Pegeout', 'Honda Fit', 'Honda CRV'))
15+
16+
testthat::expect_equal(get_col_types(data=d), c("text"))
17+
})
18+
19+
test_that("'get_col_types' argument gives character if 'data' a dataframe or matrix", {
20+
d <- data.frame(Model = c('Mazda', 'Pegeout', 'Honda Fit', 'Honda CRV'),
21+
Availability = c(TRUE, FALSE, TRUE, TRUE))
22+
testthat::expect_equal(get_col_types(data=d), c("text", "checkbox"))
23+
})
24+
25+
test_that("'get_col_types' argument gives character if 'data' a dataframe or matrix", {
26+
d <- data.frame(Model = c('Mazda', 'Pegeout', 'Honda Fit', 'Honda CRV'),
27+
Date=c(as.Date('2006-01-01'), as.Date('2005-01-01'),
28+
as.Date('2004-01-01'), as.Date('2003-01-01' )))
29+
30+
testthat::expect_equal(get_col_types(data=d), c("text", "calendar"))
31+
})
32+
33+
test_that("'get_col_types' argument gives character if 'data' a dataframe or matrix", {
34+
d <- data.frame( value = c(0.1, 0.2, 0.3))
35+
testthat::expect_equal(get_col_types(data=d), c("numeric"))
36+
})
37+
38+
test_that("'get_col_types' argument gives character if 'data' a dataframe or matrix", {
39+
d <- data.frame( value = LETTERS[1:10], stringsAsFactors = FALSE)
40+
testthat::expect_equal(get_col_types(data=d), c("text"))
41+
})
42+
43+
test_that("'get_col_types' argument gives character if 'data' a dataframe or matrix", {
44+
d <- data.frame( value = c(1, 2.5, 4.5) )
45+
testthat::expect_equal(get_col_types(data=d), c("numeric"))
46+
})
47+
48+
test_that("'get_col_types' argument gives error if 'data' not a dataframe or matrix", {
49+
d <- 1
50+
testthat::expect_error(get_col_types(data = d), c("'data' must be either a matrix or a data frame, cannot be numeric"))
51+
})
52+
53+
test_that("'get_col_types' argument gives character if 'data' a dataframe or matrix", {
54+
d <- matrix( c(as.double(1), as.double(2.5)), ncol=1)
55+
testthat::expect_equal(get_col_types(data=d), c("numeric"))
56+
})

0 commit comments

Comments
 (0)