Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
T
tallty_import_export
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
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
open-source
tallty_import_export
Commits
bb9bbe82
Commit
bb9bbe82
authored
May 02, 2022
by
Ivan Lan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 数据好像对了
parent
49c7e59a
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
403 additions
and
62 deletions
+403
-62
tallty_import_export.rb
lib/tallty_import_export.rb
+4
-1
export_header.rb
lib/tallty_import_export/attr/export_header.rb
+16
-19
export_form.rb
lib/tallty_import_export/export_form.rb
+133
-0
export_payload.rb
lib/tallty_import_export/export_payload.rb
+250
-42
No files found.
lib/tallty_import_export.rb
View file @
bb9bbe82
require
'active_support'
require
"active_support/core_ext/hash"
require
"active_support/core_ext/hash"
require
"active_support/core_ext/object"
require
"tallty_import_export/version"
require
"tallty_import_export/version"
require
'axlsx'
require
'axlsx'
require
'redis'
require
'redis'
require
'tallty_form'
#
require 'tallty_form'
require
'attr_json'
require
'attr_json'
module
TalltyImportExport
module
TalltyImportExport
...
@@ -18,6 +20,7 @@ module TalltyImportExport
...
@@ -18,6 +20,7 @@ module TalltyImportExport
autoload
:Excel
autoload
:Excel
autoload
:Attr
autoload
:Attr
autoload
:ExportPayload
autoload
:ExportPayload
autoload
:ExportForm
class
Error
<
StandardError
;
end
class
Error
<
StandardError
;
end
...
...
lib/tallty_import_export/attr/export_header.rb
View file @
bb9bbe82
...
@@ -17,20 +17,23 @@ module TalltyImportExport
...
@@ -17,20 +17,23 @@ module TalltyImportExport
attr_json
:proc
,
ActiveModel
::
Type
::
Value
.
new
,
array:
true
attr_json
:proc
,
ActiveModel
::
Type
::
Value
.
new
,
array:
true
attr_json
:children
,
self
.
to_type
,
array:
true
attr_json
:children
,
self
.
to_type
,
array:
true
def
depth
attr_accessor
:depth
,
:parent_path
,
:seq
children
&
.
count
.
to_i
+
1
end
# 取叶子结点,获取到excel表格的宽度
def
calcute_flatten_value
_depth
,
_parent_path
def
leaves
@depth
=
_depth
if
children
.
present?
@parent_path
=
_parent_path
children
.
flat_map
do
|
child
|
if
children
child
.
leaves
children
.
map
do
|
child
|
end
child
.
calcute_flatten_value
(
_depth
+
1
,
[
*
_parent_path
,
self
])
end
.
compact
.
flatten
else
else
[
self
]
[
self
]
end
end
end
end
def
seq
@seq
||=
SecureRandom
.
uuid
end
end
end
class
ExportHeader
class
ExportHeader
...
@@ -39,17 +42,11 @@ module TalltyImportExport
...
@@ -39,17 +42,11 @@ module TalltyImportExport
attr_json
:items
,
ExportHeaderItem
.
to_type
,
array:
true
attr_json
:items
,
ExportHeaderItem
.
to_type
,
array:
true
def
depth
def
flatten_value
items
.
map
(
&
:depth
).
max
items
.
map
do
|
item
|
item
.
calcute_flatten_value
(
0
,
[])
end
.
flatten
end
end
# def height payload
# items.map do |item|
# TalltyImportExport::ExportPayload.new(header: item, payload: payload[item.key])
# end.map do |export_payload|
# export_payload.height
# end.max
# end
end
end
end
end
end
end
lib/tallty_import_export/export_form.rb
0 → 100644
View file @
bb9bbe82
module
TalltyImportExport
class
ExportForm
<
TalltyImportExport
::
Export
def
initialize
super
({})
end
class
<<
self
def
form_transfer_to_headers
form
end
end
def
export_workbook
workbook
,
association_records
,
**
options
# excel导出样式
# alignment = { vertical: :center, horizontal: :center }
# border = { color: '969696', style: :thin }
# title1 = workbook.styles.add_style(alignment: alignment, border: border, sz: 12, b: true)
# title2 = workbook.styles.add_style(alignment: alignment, border: border, bg_color: "2a5caa", sz: 12, fg_color: "fffffb")
# title3 = workbook.styles.add_style(alignment: alignment.merge(wrap_text: true), border: border, sz: 10)
headers
=
export_headers_result
**
options
p
headers
.
flatten_value
.
map
(
&
:key
)
# _sheet_name = respond_to?(:sheet_name) ? self.sheet_name : nil
# workbook.add_worksheet(name: _sheet_name) do |sheet|
# if respond_to?(:first_header)
# row_index = Axlsx.col_ref(headers.size - 1)
# sheet.merge_cells("A1:#{row_index}1")
# sheet.add_row [first_header], style: title1, height: 30
# end
# sheet.add_row headers.map{|header| header[:name]}, style: title2, height: 25
# last_row = nil
# merge_column_hash = {}
# first_content_row_index = respond_to?(:first_header) ? 2 : 1
index
=
0
association_records
.
each
do
|
association_record
|
records
=
@each_method
.
present?
?
(
try_method
(
association_record
,
@each_method
)
||
[
nil
])
:
[
association_record
]
records
.
each
do
|
record
|
row
=
[]
formats
=
[]
index
+=
1
lines
=
TalltyImportExport
::
ExportPayload
.
new
(
record
,
headers:
headers
)
do
|
payload
,
header
|
# p "payload: #{payload} -- header[:key] #{header[:key]}"
_data
=
header
[
:source
]
?
handle_data
(
association_record
,
header
,
index
)
:
handle_data
(
payload
,
header
,
index
)
end
.
lines
result
=
[]
lines
.
transpose
.
map
do
|
transposed_line
|
line
=
transposed_line
while
line
[
0
].
nil?
line
.
shift
line
.
push
(
false
)
end
line
# transposed_line.compact
end
.
transpose
.
each
do
|
line
|
if
line
.
select
(
&
:itself
).
count
>
0
result
<<
line
.
map
{
|
x
|
x
||
'________'
}
end
end
# result = []
# cache[0].length.times do
# cache.each_with_index do |line, index|
# result[index] = [] unless result[index]
# result[index] << line[index]
# end
# end
p
'----------------------------------------------------------------'
result
.
uniq
.
sort
.
each
{
|
x
|
p
x
}
# headers.each_with_index do |header, col_index|
# _data = header[:source] ?
# handle_data(association_record, header, index) :
# handle_data(record, header, index)
# if header[:merge].present? && last_row.present? && _data == last_row[col_index]
# # 这里使用二维数组,每个数组里都是列内容相同的各行
# merge_column_hash[col_index] ||= []
# if merge_column_hash[col_index].last&.last == index + first_content_row_index - 1
# # 说明内容和上面的是延续的,继续加入之前的数组
# merge_column_hash[col_index].last << index + first_content_row_index
# else
# merge_column_hash[col_index] << [index + first_content_row_index - 1, index + first_content_row_index]
# end
# end
# row.push(_data)
# formats.push(header[:format]&.to_sym || (_data.is_a?(String) ? :string : nil))
# end
# sheet.add_row row, style: title3, height: @row_height, types: formats
# last_row = row
end
end
# # 需要根据column进行多行的内容合并
# if merge_column_hash.present?
# merge_column_hash.each do |col_index, row_arr|
# row_arr.each do |arr|
# sheet.merge_cells(
# Axlsx::cell_r(col_index, arr.first) + ':' + Axlsx::cell_r(col_index, arr.last)
# )
# end
# end
# end
# sheet.column_widths(*headers.map{|header| (header[:width] || @width).to_f})
# end
end
def
export_headers_result
**
options
@headers
=
options
[
:headers
]
super
(
**
options
)
@headers
=
TalltyImportExport
::
Attr
::
ExportHeader
.
new
({
items:
@headers
})
end
end
end
lib/tallty_import_export/export_payload.rb
View file @
bb9bbe82
# class TalltyImportExport::ExportPayload
# # header: 导出时候使用的配置模型
# # payload: 对应的单行数据抽取,如果是list属性,则payload是一个array
# attr_accessor :header, :payload, :children, :parent
# def initialize(header:, payload:, parent: nil, children: [])
# @header = header
# @payload = payload
# @children = []
# @parent = parent
# # 递归生成
# if header.is_a?(TalltyImportExport::Attr::ExportHeader)
# @children = header.items.map do |header_item|
# self.class.new(
# header: header_item,
# payload: payload_value(header: header_item, payload: payload),
# parent: self
# )
# end
# else
# if header.children.present?
# @children = header.children.map do |header_item|
# self.class.new(
# header: header_item,
# payload: payload_value(header: header_item, payload: payload),
# parent: self
# )
# end
# end
# end
# end
# def height
# return 0 if payload.blank?
# if header.children.blank?
# # 单属性,如果有值,为1,没有值为0
# payload.present? ? 1 : 0
# else
# # list属性,payload是array
# # 高度是表格里所有属性的height的最大值
# children_height_arr = header.children.map do |header_child|
# Array(payload).map do |payload_child|
# self.class.new(
# header: header_child,
# payload: payload_value(header: header_child, payload: payload_child),
# ).height
# end.sum
# end.max
# end
# end
# # TODO 获取值的方法
# def payload_value header:, payload:
# payload&.dig(header.key)
# end
# end
class
TalltyImportExport
::
ExportPayload
class
TalltyImportExport
::
ExportPayload
# header: 导出时候使用的配置模型
attr_reader
:value
,
:context
# payload: 对应的单行数据抽取,如果是list属性,则payload是一个array
attr_accessor
:header
,
:payload
,
:children
,
:parent
def
initialize
(
header
:,
payload
:,
parent:
nil
,
children:
[])
def
initialize
(
val
,
headers
:,
&
value_handler
)
@value
=
TalltyImportExport
::
ExportPayload
::
Value
.
new
(
val
)
@headers
=
headers
.
items
# TalltyImportExport::Attr::ExportHeaderItem array
@flatten_headers
=
headers
.
flatten_value
@value_handler
=
value_handler
@context
=
{
# header_seq_to_cell_seq_to_header_seq_to_value_mapping: {},
value_seq_to_header_seq_to_value:
{},
# header_seq_to_header_mapping: @headers.reduce({}) do |out, header|
# out[header.seq] = header
# out
# end,
# header_seq_to_children_mapping: @headers.reduce({}) do |out, header|
# out[header.seq] = header.children
# out
# end,
flatten_headers:
@flatten_headers
,
}
end
def
lines
cell_columns
=
@headers
.
map
do
|
header
|
TalltyImportExport
::
ExportPayload
::
CellColumn
.
new
(
header
,
self
.
value
,
@context
,
&
@value_handler
)
end
max_height_cell_column
=
cell_columns
.
map
(
&
:flatten_cells
).
max
do
|
a
,
b
|
a
.
count
<=>
b
.
count
end
max_height_cell_column
.
map
(
&
:grow_to_line
)
end
end
class
TalltyImportExport
::
ExportPayload
::
Value
attr_reader
:value
,
:seq_chain
def
initialize
val
,
seq_chain
=
[]
@value
=
val
@seq_chain
=
[
*
seq_chain
,
seq
]
# flatten_cells.each do |cell|
# context[:cell_seq_to_header_seq_to_value][cell.seq] = {} unless context[:cell_seq_to_header_seq_to_value][cell.seq]
# context[:cell_seq_to_header_seq_to_value][cell.seq][header.seq] = value
end
def
seq
@seq
||=
SecureRandom
.
uuid
end
end
# 一个 竖列
class
TalltyImportExport
::
ExportPayload
::
CellColumn
attr_reader
:header
,
:payload
,
:context
,
:cell_clusters
,
:flatten_cells
def
initialize
header
,
value
,
context
,
&
value_handler
@header
=
header
@header
=
header
@payload
=
payload
@value
=
value
@children
=
[]
@context
=
context
@parent
=
parent
@cell_clusters
=
[]
@value_handler
=
value_handler
# 递归生成
if
header
.
is_a?
(
TalltyImportExport
::
Attr
::
ExportHeader
)
if
header
.
children
@children
=
header
.
items
.
map
do
|
header_item
|
@cell_clusters
=
@value
.
value
[
header
.
key
.
to_sym
].
map
do
|
val
|
self
.
class
.
new
(
TalltyImportExport
::
ExportPayload
::
Cell
.
new
(
header:
header_item
,
@header
,
payload:
payload_value
(
header:
header_item
,
payload:
payload
),
TalltyImportExport
::
ExportPayload
::
Value
.
new
(
val
,
@value
.
seq_chain
),
parent:
self
@context
,
&
@value_handler
)
)
end
end
else
else
if
header
.
children
.
present?
@cell_clusters
=
[
@children
=
header
.
children
.
map
do
|
header_item
|
TalltyImportExport
::
ExportPayload
::
Cell
.
new
(
self
.
class
.
new
(
@header
,
header:
header_item
,
TalltyImportExport
::
ExportPayload
::
Value
.
new
(
payload:
payload_value
(
header:
header_item
,
payload:
payload
),
@value_handler
.
call
(
@value
.
value
,
@header
.
as_json
.
symbolize_keys
),
parent:
self
@value
.
seq_chain
,
)
),
end
@context
,
&
@value_handler
)
]
end
@flatten_cells
=
[]
cell_divise
end
def
cell_divise
@flatten_cells
=
@cell_clusters
.
map
do
|
cell_cluster
|
cell_cluster
.
divise
.
cell_cluster
end
.
flatten
self
end
end
class
TalltyImportExport
::
ExportPayload
::
Cell
attr_accessor
:cell_cluster
,
:val
,
:header
,
:parent_path
# cell_cluster 是表格纵向 集合
# cell_the_same_line 是表格横向 集合
def
initialize
header
,
value
,
context
,
parent_path
=
[],
&
value_handler
@value
=
value
@header
=
header
@value_handler
=
value_handler
# context
@context
=
context
# unless (@context[:header_seq_to_cell_seq_to_header_seq_to_value_mapping][header.seq])
# @context[:header_seq_to_cell_seq_to_header_seq_to_value_mapping][header.seq] = {}
# end
# @context[:header_seq_to_cell_seq_to_header_seq_to_value_mapping][header.seq][seq] = value
value
.
seq_chain
.
each
do
|
s
|
unless
(
@context
[
:value_seq_to_header_seq_to_value
][
s
])
@context
[
:value_seq_to_header_seq_to_value
][
s
]
=
{}
end
end
@context
[
:value_seq_to_header_seq_to_value
][
s
][
header
.
seq
]
=
value
.
value
end
end
# parent
@parent_path
=
parent_path
@cell_cluster
=
[]
end
end
def
height
def
seq
return
0
if
payload
.
blank?
@seq
||=
SecureRandom
.
uuid
end
def
heredity_chain
[
*
self
.
parent_path
,
self
]
end
if
header
.
children
.
blank?
def
divise
# 单属性,如果有值,为1,没有值为0
if
@header
.
children
.
present?
payload
.
present?
?
1
:
0
new_cells
=
@header
.
children
.
map
do
|
child_header
|
if
(
child_header
.
children
.
present?
)
val
=
@value
.
value
[
child_header
.
key
.
to_sym
]
val
.
map
do
|
val
|
TalltyImportExport
::
ExportPayload
::
Cell
.
new
(
child_header
,
TalltyImportExport
::
ExportPayload
::
Value
.
new
(
val
,
@value
.
seq_chain
),
@context
,
[
*
self
.
parent_path
,
self
],
&
@value_handler
)
end
else
val
=
@value_handler
.
call
(
@value
.
value
,
child_header
.
as_json
.
symbolize_keys
)
TalltyImportExport
::
ExportPayload
::
Cell
.
new
(
child_header
,
TalltyImportExport
::
ExportPayload
::
Value
.
new
(
val
,
@value
.
seq_chain
),
@context
,
[
*
self
.
parent_path
,
self
],
&
@value_handler
)
end
end
.
flatten
new_cells
.
each
(
&
:divise
)
@cell_cluster
.
concat
(
new_cells
.
map
(
&
:cell_cluster
))
else
else
# list属性,payload是array
@cell_cluster
=
[
self
]
# 高度是表格里所有属性的height的最大值
children_height_arr
=
header
.
children
.
map
do
|
header_child
|
Array
(
payload
).
map
do
|
payload_child
|
self
.
class
.
new
(
header:
header_child
,
payload:
payload_value
(
header:
header_child
,
payload:
payload_child
),
).
height
end
.
sum
end
.
max
end
end
end
# TODO 获取值的方法
self
def
payload_value
header
:,
payload:
payload
&
.
dig
(
header
.
key
)
end
end
def
grow_to_line
# heredity_chain_seq = heredity_chain.map(&:seq)
@context
[
:flatten_headers
].
map
do
|
header
|
# cell_seq_to_header_seq_to_value_mapping = @context[:header_seq_to_cell_seq_to_header_seq_to_value_mapping][header.seq]
# target_val = nil
# heredity_chain_seq.each do |seq|
# if cell_seq_to_header_seq_to_value_mapping[seq]
# target_val = cell_seq_to_header_seq_to_value_mapping[seq]
# end
# end
# target_val
target_val
=
nil
@value
.
seq_chain
.
each
do
|
seq
|
if
@context
[
:value_seq_to_header_seq_to_value
][
seq
]
&
.
[
](
header
.
seq
)
target_val
=
@context
[
:value_seq_to_header_seq_to_value
][
seq
][
header
.
seq
]
end
end
target_val
end
end
end
end
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