Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
R
Radiant
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wuzekai
Radiant
Commits
21174836
Commit
21174836
authored
Nov 26, 2025
by
gaozhaochen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update: 自动加载xlsx的全部sheet数据
parent
ae842bf1
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
113 additions
and
55 deletions
+113
-55
init_load_data.R
radiant.data/inst/app/tools/data/init_load_data.R
+39
-28
manage.R
radiant.data/inst/app/tools/data/manage.R
+74
-27
No files found.
radiant.data/inst/app/tools/data/init_load_data.R
View file @
21174836
...
...
@@ -8,38 +8,36 @@ observe({
dataset_id
<-
query
[[
'datasetId'
]]
token
<-
query
[[
'token'
]]
# 初始化一个 session 级别的变量来记录已加载的 ID,防止刷新时的重复请求
if
(
is.null
(
session
$
userData
$
loaded_datasets
))
{
session
$
userData
$
loaded_datasets
<-
c
()
}
# 2. 仅当 ID 和 Token 均存在时执行
if
(
!
is.null
(
dataset_id
)
&&
!
is.null
(
token
))
{
# 定义 Radiant 内部使用的数据集名称 (例如: data_10086)
# 如果 URL 传了 name 参数就用 name,否则用 id 拼接
ds_name
<-
if
(
!
is.null
(
query
[[
'name'
]]))
query
[[
'name'
]]
else
paste0
(
"data_"
,
dataset_id
)
# 3. 检查数据是否已存在 (防止重复加载)
if
(
is.null
(
r_data
[[
ds_name
]]))
{
# 3. [修改点] 检查 ID 是否已在本次会话中加载过
# 因为现在数据集名称是动态的 Sheet 名,下载前无法预知,所以改为判断 ID
if
(
!
(
dataset_id
%in%
session
$
userData
$
loaded_datasets
))
{
withProgress
(
message
=
'正在从业务系统同步数据...'
,
value
=
0.2
,
{
# 4. 获取环境变量中的 API 基地址
# api_base <- Sys.getenv("HOST_API_BASE","http://127.0.0.1:11999")
api_base
<-
Sys.getenv
(
"HOST_API_BASE"
,
"https://ds.cixincloud.com/data-search-api"
)
# 4. 获取环境变量
api_base
<-
Sys.getenv
(
"HOST_API_BASE"
,
"https://ds.cixincloud.com/data-search-api"
)
# 5. 拼接完整 API 路径
# target_url <- paste0(api_base, "/disease-data/data/export/apply/apply/case?applyId=", dataset_id)
target_url
<-
paste0
(
api_base
,
"/research-project/generate-project-dataset/"
,
dataset_id
)
# 6. 创建临时文件
(明确 .xlsx 后缀)
# 6. 创建临时文件
tmp_file
<-
tempfile
(
fileext
=
".xlsx"
)
tryCatch
({
incProgress
(
0.3
,
detail
=
"正在鉴权并下载..."
)
# 7.
发起带 Token 的
HTTP 请求
# 7. HTTP 请求
response
<-
httr
::
POST
(
url
=
target_url
,
# 添加 Bearer Token (或根据你的接口要求修改 Header)
httr
::
add_headers
(
authentication
=
paste
(
token
)),
# 将结果写入磁盘
httr
::
write_disk
(
tmp_file
,
overwrite
=
TRUE
)
)
...
...
@@ -47,34 +45,47 @@ observe({
print
(
response
$
request
)
message
(
"==================="
)
# 检查 HTTP 状态码
if
(
httr
::
status_code
(
response
)
!=
200
)
{
stop
(
paste
(
"下载失败,
请手动导入,
HTTP状态码:"
,
httr
::
status_code
(
response
)))
stop
(
paste
(
"下载失败,HTTP状态码:"
,
httr
::
status_code
(
response
)))
}
incProgress
(
0.7
,
detail
=
"解析并导入 Radiant..."
)
# 8.
复用 Radiant 核心加载函数 (manage_ui.R 中定义)
#
这会自动完成读取、转因子、生成R代码、注册到下拉框等所有动作
# 8.
调用核心加载函数
#
注意:这里的 fname 仅用于扩展名识别,实际数据集名称由 Sheet 名决定
load_user_data
(
fname
=
paste0
(
ds_name
,
".xlsx"
),
# 虚拟文件名
uFile
=
tmp_file
,
# 实际文件路径
fname
=
"downloaded_data.xlsx"
,
uFile
=
tmp_file
,
ext
=
"xlsx"
,
xlsx_sheet
=
1
,
xlsx_header
=
TRUE
,
man_str_as_factor
=
TRUE
)
# 9. 界面联动:选中数据并跳转到视图
updateSelectInput
(
session
,
"dataset"
,
selected
=
ds_name
)
# 9. 界面联动:获取刚才加载的 Sheet 名称并选中第一个
# 必须再次读取 Sheet 列表并做 make.names 处理,才能匹配到 r_data 中的 Key
loaded_sheets
<-
try
(
readxl
::
excel_sheets
(
tmp_file
),
silent
=
TRUE
)
if
(
!
inherits
(
loaded_sheets
,
"try-error"
)
&&
length
(
loaded_sheets
)
>
0
)
{
# 必须和 load_user_data 里的逻辑一致,使用 make.names 清洗
valid_names
<-
make.names
(
loaded_sheets
)
first_sheet_name
<-
valid_names
[
1
]
# 默认选第一个
# 标记为已加载
session
$
userData
$
loaded_datasets
<-
c
(
session
$
userData
$
loaded_datasets
,
dataset_id
)
# 更新下拉框并选中第一个 Sheet
updateSelectInput
(
session
,
"dataset"
,
selected
=
first_sheet_name
)
updateTabsetPanel
(
session
,
"nav_radiant"
,
selected
=
"Data"
)
updateTabsetPanel
(
session
,
"tabs_data"
,
selected
=
"View"
)
# 或者 "Visualize"
updateTabsetPanel
(
session
,
"tabs_data"
,
selected
=
"View"
)
showNotification
(
paste
(
"数据集"
,
ds_name
,
"加载成功!"
),
type
=
"message"
)
showNotification
(
paste0
(
"成功加载 "
,
length
(
valid_names
),
" 个数据集 (ID: "
,
dataset_id
,
")"
),
type
=
"message"
)
}
else
{
showNotification
(
"文件下载成功,但未发现有效的 Sheet"
,
type
=
"warning"
)
}
},
error
=
function
(
e
)
{
showNotification
(
paste
(
"数据同步失败,请手动导入数据:"
,
e
$
message
),
type
=
"error"
,
duration
=
10
)
#调试打印 print(e)
showNotification
(
paste
(
"数据同步失败:"
,
e
$
message
),
type
=
"error"
,
duration
=
10
)
})
})
}
...
...
radiant.data/inst/app/tools/data/manage.R
View file @
21174836
...
...
@@ -142,35 +142,77 @@ load_user_data <- function(fname, uFile, ext, header = TRUE,
}
}
else
if
(
ext
==
"xlsx"
)
{
if
(
!
requireNamespace
(
"readxl"
,
quietly
=
TRUE
))
{
ret
<-
i
18
n
$
t
(
"#### 读取xlsx文件需要readxl包"
)
upload_error_handler
(
objname
,
ret
)
}
else
{
# 用readxl读取xlsx
robj
<-
try
(
readxl
::
read_excel
(
upload_error_handler
(
objname
,
i
18
n
$
t
(
"#### 需要安装 readxl 包"
))
return
()
}
# 1. 获取所有 Sheet
all_sheets
<-
try
(
readxl
::
excel_sheets
(
path
=
uFile
),
silent
=
TRUE
)
if
(
inherits
(
all_sheets
,
"try-error"
))
{
upload_error_handler
(
objname
,
i
18
n
$
t
(
"#### 无法解析 Excel 文件结构"
))
return
()
}
loaded_count
<-
0
# 2. 循环处理
for
(
sheet_name
in
all_sheets
)
{
# 2.1 准备合法的变量名
clean_name
<-
make.names
(
sheet_name
)
if
(
clean_name
==
""
)
clean_name
<-
paste0
(
"Sheet_"
,
sample
(
1000
,
1
))
# 2.2 读取数据
raw_data
<-
try
(
readxl
::
read_excel
(
path
=
uFile
,
sheet
=
xlsx_sheet
,
# 对应UI的“工作表索引”
col_names
=
xlsx_header
# 对应UI的“第一行为表头”
sheet
=
sheet_name
,
col_names
=
xlsx_header
),
silent
=
TRUE
)
if
(
inherits
(
robj
,
"try-error"
))
{
upload_error_handler
(
objname
,
i
18
n
$
t
(
"#### 读取xlsx文件失败,请检查文件是否损坏或格式正确"
))
}
else
{
# 转换为data.frame并处理因子
r_data
[[
objname
]]
<-
as.data.frame
(
robj
,
stringsAsFactors
=
FALSE
)
%>%
{
if
(
man_str_as_factor
)
radiant.data
::
to_fct
(
.
)
else
.
}
# 生成R代码
cmd
<-
glue
(
'
{objname} <- readxl::read_excel(
{pp$rpath},
sheet = {xlsx_sheet},
col_names = {xlsx_header}
) %>%
as.data.frame(stringsAsFactors = FALSE)
{if (man_str_as_factor) paste0(objname, " <- radiant.data::to_fct(", objname, ")") else ""}
register("{objname}")
# 2.3 卫语句:跳过无效数据(空表或读取错误)
if
(
inherits
(
raw_data
,
"try-error"
)
||
!
is.data.frame
(
raw_data
)
||
ncol
(
raw_data
)
==
0
)
{
next
}
# 2.4 [关键] 立即执行 Radiant 标准数据清洗流程
# 必须在循环内做,因为我们不会走到函数底部的通用处理逻辑了
try
({
# 清洗列名
colnames
(
raw_data
)
<-
radiant.data
::
fix_names
(
colnames
(
raw_data
))
# 转换因子
if
(
man_str_as_factor
)
raw_data
<-
radiant.data
::
to_fct
(
raw_data
)
},
silent
=
TRUE
)
# 2.5 入库
r_data
[[
clean_name
]]
<-
as.data.frame
(
raw_data
,
stringsAsFactors
=
FALSE
)
# 2.6 生成并注册复现代码 (Reproducibility)
# 注意:这里直接注册 register,不需要 cmd 变量在外部累加
curr_cmd
<-
glue
::
glue
(
'
{clean_name} <- readxl::read_excel("{uFile}", sheet = "{sheet_name}", col_names = {xlsx_header}) %>%
as.data.frame(stringsAsFactors = FALSE) %>%
fix_names()
{if (man_str_as_factor) paste0(clean_name, " <- radiant.data::to_fct(", clean_name, ")") else ""}
register("{clean_name}")
'
)
# 2.7 更新系统元数据 (Mimic bottom logic)
if
(
exists
(
clean_name
,
envir
=
r_data
)
&&
!
bindingIsActive
(
as.symbol
(
clean_name
),
env
=
r_data
))
{
shiny
::
makeReactiveBinding
(
clean_name
,
env
=
r_data
)
}
r_info
[[
glue
(
"{clean_name}_lcmd"
)]]
<-
curr_cmd
r_info
[[
"datasetlist"
]]
<-
unique
(
c
(
clean_name
,
r_info
[[
"datasetlist"
]]))
loaded_count
<-
loaded_count
+
1
}
if
(
loaded_count
==
0
)
{
upload_error_handler
(
objname
,
i
18
n
$
t
(
"#### 文件中未发现有效的表格数据"
))
}
# 直接返回
return
()
}
else
if
(
ext
%in%
c
(
"tsv"
,
"csv"
,
"txt"
))
{
r_data
[[
objname
]]
<-
load_csv
(
uFile
,
...
...
@@ -197,6 +239,11 @@ load_user_data <- function(fname, uFile, ext, header = TRUE,
upload_error_handler
(
objname
,
ret
)
}
# ===========================================================================
# 下面的代码只为单数据集流程(CSV, RDS, parquet)服务
# XLSX 流程已经在上面 return() 了,不会执行到这里
# ===========================================================================
if
(
exists
(
objname
,
envir
=
r_data
)
&&
!
bindingIsActive
(
as.symbol
(
objname
),
env
=
r_data
))
{
shiny
::
makeReactiveBinding
(
objname
,
env
=
r_data
)
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment