赞
踩
SAP 对法定的会计报表,比如资产负债表,损益表等,有多种实现方案。这里给出一个集成 Excel 的实现方案。实现方案的主要优点是用户的自由度比较大,可以灵活设置,而且基本实现了一次开发,不同项目只需要部署就能使用。
数据字段说明:
以【货币资金】为例,D7 单元格的公式:=AccAmount(BS_Source!B:B,K7,BS_Source!J:J)
,AccAmount
是自定义的函数名,表示获取会计科目的期末余额。我们先不管这个函数参数是什么意思,总之是实现自动取数,文章后面会详细说明。
SAP 提供的函数 BAPI_GL_GETGLACCPERIODBALANCES
只能提供单个科目的会计余额,我们要导入的是批量数据,所以需要自定义一个函数。写法可以多种,这里给出一个示例代码:
- FUNCTION zbapi_getglaccperiodbalances.
- *"----------------------------------------------------------------------
- *"*"局部接口:
- *" IMPORTING
- *" VALUE(COMPANYCODE) LIKE FAGLFLEXT-RBUKRS OPTIONAL
- *" VALUE(FISCALYEAR) LIKE FAGLFLEXT-RYEAR OPTIONAL
- *" VALUE(PERIOD) LIKE FAGLFLEXT-RPMAX OPTIONAL
- *" VALUE(CURRENCYTYPE) LIKE BAPI1028_5-CURR_TYPE OPTIONAL
- *" EXPORTING
- *" VALUE(BALANCE_CARRIED_FORWARD) LIKE BAPI1028_4-BALANCE
- *" VALUE(RETURN) LIKE BAPIRETURN STRUCTURE BAPIRETURN
- *" TABLES
- *" ACCOUNT_BALANCES STRUCTURE ZBALANCES OPTIONAL
- *" EXCEPTIONS
- *" INIT_DATA
- *"----------------------------------------------------------------------
-
- DATA: BEGIN OF lt_fag OCCURS 0,
- bukrs LIKE faglflext-rbukrs, "公司代码
- ryear LIKE faglflext-ryear, "会计年度
- racct LIKE faglflext-racct, "会计科目
- drcrk LIKE faglflext-drcrk, "借贷方
- hslvt LIKE faglflext-hslvt,
- hsl01 LIKE faglflext-hsl01,
- hsl02 LIKE faglflext-hsl02,
- hsl03 LIKE faglflext-hsl03,
- hsl04 LIKE faglflext-hsl04,
- hsl05 LIKE faglflext-hsl05,
- hsl06 LIKE faglflext-hsl06,
- hsl07 LIKE faglflext-hsl07,
- hsl08 LIKE faglflext-hsl08,
- hsl09 LIKE faglflext-hsl09,
- hsl10 LIKE faglflext-hsl10,
- hsl11 LIKE faglflext-hsl11,
- hsl12 LIKE faglflext-hsl12,
- hsl13 LIKE faglflext-hsl13,
- hsl14 LIKE faglflext-hsl14,
- hsl15 LIKE faglflext-hsl15,
- hsl16 LIKE faglflext-hsl16,
- END OF lt_fag,
-
- lt_ret LIKE zbalances OCCURS 0 WITH HEADER LINE.
-
- FIELD-SYMBOLS: <field>.
-
- DATA: lv_idx TYPE i,
- lv_times TYPE i,
- lv_int TYPE i,
- lv_rpmax(2) TYPE c,
- lv_fieldname TYPE string,
- lv_hslxx LIKE faglflext-hslvt,
- lv_waers LIKE t001-waers.
-
- * 公司本位币
- SELECT SINGLE waers
- INTO lv_waers
- FROM t001
- WHERE bukrs = companycode.
-
- SELECT rbukrs AS bukrs
- ryear
- racct
- drcrk
- hslvt
- hsl01
- hsl02
- hsl03
- hsl04
- hsl05
- hsl06
- hsl07
- hsl08
- hsl09
- hsl10
- hsl11
- hsl12
- hsl13
- hsl14
- hsl15
- hsl16
- INTO TABLE lt_fag
- FROM faglflext
- WHERE rbukrs = companycode
- and ryear = fiscalyear.
-
- SORT lt_fag BY bukrs ryear racct drcrk.
- LOOP AT lt_fag.
- AT NEW racct.
- CLEAR lt_ret.
- lt_ret-comp_code = lt_fag-bukrs.
- lt_ret-gl_account = lt_fag-racct.
- lt_ret-fisc_year = lt_fag-ryear.
- lt_ret-fis_period = period.
- lt_ret-currency = lv_waers.
- ENDAT.
-
- * 年初余额
- lt_ret-yr_begin_bal = lt_ret-yr_begin_bal + lt_fag-hslvt.
-
- IF period = 12.
- lv_times = 16.
- ELSE.
- lv_times = period.
- ENDIF.
-
- * 期初余额
- lt_ret-per_begin_bal = lt_ret-per_begin_bal + lt_fag-hslvt.
- DO lv_times TIMES.
- IF sy-index >= lv_times.
- EXIT.
- ENDIF.
-
- MOVE sy-index TO lv_rpmax.
- SHIFT lv_rpmax RIGHT DELETING TRAILING space.
- OVERLAY lv_rpmax WITH '00'.
- CONCATENATE 'HSL' lv_rpmax INTO lv_fieldname.
- ASSIGN COMPONENT lv_fieldname OF STRUCTURE lt_fag TO <field>.
- MOVE <field> TO lv_hslxx.
-
- lt_ret-per_begin_bal = lt_ret-per_begin_bal + lv_hslxx.
- ENDDO.
-
- IF period = 12.
- lv_times = 5.
- ELSE.
- lv_times = 1.
- ENDIF.
-
- * 期间发生额
- DO lv_times TIMES.
- lv_int = period + sy-index - 1.
- MOVE lv_int TO lv_rpmax.
- SHIFT lv_rpmax RIGHT DELETING TRAILING space.
- OVERLAY lv_rpmax WITH '00'.
- CONCATENATE 'HSL' lv_rpmax INTO lv_fieldname.
- ASSIGN COMPONENT lv_fieldname OF STRUCTURE lt_fag TO <field>.
- MOVE <field> TO lv_hslxx.
-
- IF lt_fag-drcrk = 'S'.
- * 期间借方
- lt_ret-debits_per = lt_ret-debits_per + lv_hslxx.
- ELSE.
- * 期间贷方
- lt_ret-credit_per = lt_ret-credit_per + lv_hslxx.
- ENDIF.
- ENDDO.
-
- AT END OF racct.
- APPEND lt_ret.
- ENDAT.
- ENDLOOP.
-
- LOOP AT lt_ret.
- lv_idx = sy-tabix.
-
- * 期间发生额(借方+贷方)
- lt_ret-period_amt = lt_ret-debits_per + lt_ret-credit_per.
-
- * 期末余额
- lt_ret-balance = lt_ret-per_begin_bal + lt_ret-period_amt.
-
- MODIFY lt_ret INDEX lv_idx.
- ENDLOOP.
-
- DELETE lt_ret WHERE yr_begin_bal = 0 AND per_begin_bal = 0 AND debits_per = 0 AND credit_per = 0.
-
- account_balances[] = lt_ret[].
- ENDFUNCTION.

函数名: zbapi_getglaccperiodbalances
。函数的参数包括公司代码,年度,期间,币别,根据参数所确定的条件,输出这些科目的期初余额,本期发生额,期末余额。代码简单,不多解释,也不是本文的重点。但顺便提一句,SAP 系统 ABAP 的编码就这么多,不像其他解决方案,可能需要大量 ABAP 编码。
从模块的角度给出代码。Excel 首先是SAP_Connection模块,负责连接 SAP 系统,登陆 (Logon) 和注销 (Logoff) 。
- ' 模块说明:
- ' 负责SAP的连接,连接成功后,SAPConnection对象保存连接的信息
-
- Option Explicit
-
- Dim sapLogon As SAPLogonCtrl.SAPLogonControl
- Public SAPConnection As SAPLogonCtrl.Connection
- Public logonSuccessful As Boolean
-
-
- Public Sub logon()
- logonSuccessful = False
-
- Set sapLogon = New SAPLogonControl
- Set SAPConnection = sapLogon.NewConnection()
-
- Call SAPConnection.logon(0, False)
-
- If SAPConnection.IsConnected = tloRfcConnected Then
- logonSuccessful = True
- Exit Sub
- End If
- End Sub
-
-
- Public Sub Logoff()
- If SAPConnection Is Nothing Then
- Exit Sub
- End If
-
- SAPConnection.Logoff
- logonSuccessful = False
- Set SAPConnection = Nothing
- End Sub

调用 SAP zbapi_getglaccperiodbalances
函数,将数据写入工作表。
首先在 VBA 中实现 ABAP内表数据(函数的表参数)写入工作表的通用实现。考虑到代码效率,数据先在内存中处理后,一次性写到工作表:
- ' 模块说明:
- ' SAP FM的表参数类似internal table, 将数据输出值EXCEL工作表
-
- Option Explicit
-
- '--------------------------------------------------
- ' 将Table对象写入worksheet, 整体拷贝,速度优化
- '--------------------------------------------------
- Public Sub WriteTable(itab As SAPTableFactoryCtrl.Table, sht As Worksheet)
- Dim col As Long ' column index
- Dim row As Long ' row index
- Dim headerRange As Variant '在Excel中根据itab的header大小,类型为Variant数组
- Dim itemsRange As Variant '在Excel中根据itab的行数和列数,类型为Variant数组
-
- ' 清除cells的内容
- sht.Cells.ClearContents
-
- If itab.RowCount = 0 Then
- Exit Sub
- End If
-
- '-------------------------------------------------
- ' 取消Excel的屏幕刷新和计算功能以加快速度
- '-------------------------------------------------
- Application.ScreenUpdating = False
- Application.Calculation = xlCalculationManual
-
- '------------------------------
- ' 将Table的Header写入Worksheet
- '------------------------------
-
- ' 根据内表的列数,使用Range创建一个数组
- Dim headerstarts As Range
- Dim headerends As Range
- Set headerstarts = sht.Cells(1, 1)
- Set headerends = sht.Cells(1, itab.ColumnCount)
-
- headerRange = sht.Range(headerstarts, headerends).Value
-
- ' 将内表列名写入数组
- For col = 1 To itab.ColumnCount
- headerRange(1, col) = itab.Columns(col).Name
- Next
-
- ' 从数组一次性写入Excel,这样效率较高
- sht.Range(headerstarts, headerends).Value = headerRange
-
- '-------------------------------
- ' 将Table的行项目写入Worksheet
- '-------------------------------
-
- ' 根据内表的大小,使用Range创建数组
- Dim itemStarts As Range
- Dim itemEnds As Range
-
- Set itemStarts = sht.Cells(2, 1)
- Set itemEnds = sht.Cells(itab.RowCount + 1, itab.ColumnCount)
- itemsRange = itab.Data
-
- ' 一次性将数组写入Worksheet
- sht.Range(itemStarts, itemEnds).Value = itemsRange
-
- '---------------------------------
- ' 恢复Excel的屏幕刷新和计算
- '---------------------------------
- Application.ScreenUpdating = True
- Application.Calculation = xlCalculationAutomatic
- Application.Calculate
- End Sub

然后是调用 zbapi_getglaccperiodbalances
函数,代码在sap_get_acc_period_bal模块:
- ' 模块说明:
- ' 调用RFC获取公司代码会计科目的余额,写入工作表
- '
- ' v1.0, 2015-6-14 by Stone Wang
- ' V1.1, 2015-6-26 by Stone Wang
-
- Option Explicit
-
- Public Sub get_sap_acc_balances(cocd As String, fiscal_yr As String, period As String)
- ' 导入SAP科目余额,写入BS_Source工作表
-
- Dim sapFunctions As SAPFunctionsOCX.sapFunctions
- Dim sapFunction As Object
- Dim acBalanceTable As Object
-
- ' 写入的工作表
- Dim sht As Worksheet
- Set sht = BSSource
-
- If logonSuccessful = False Then Exit Sub
-
- Set sapFunctions = CreateObject("SAP.FUNCTIONS") ' Use function to call BAPI
- Set sapFunctions.Connection = SAPConnection
-
- On Error GoTo err1:
- Set sapFunction = sapFunctions.Add("ZBAPI_GETGLACCPERIODBALANCES")
-
- ' Function import parameters
- sapFunction.Exports("COMPANYCODE").Value = cocd 'Company code
- sapFunction.Exports("FISCALYEAR").Value = fiscal_yr 'Fiscal year
- sapFunction.Exports("PERIOD").Value = period
- sapFunction.Exports("CURRENCYTYPE").Value = "10" 'Currency type
-
- ' Function table parameters
- Set acBalanceTable = sapFunction.Tables("ACCOUNT_BALANCES")
-
- If sapFunction.Call = True Then
- If acBalanceTable.RowCount > 0 Then
- sht.Activate
- '将internal table写入工作表
- Call WriteTable(acBalanceTable, sht)
- Else
- sht.Activate
- sht.Cells.ClearContents
- sht.Range("A1").Value = "没有数据被导入,数据源可能为空!"
- End If
- End If
-
- Set acBalanceTable = Nothing
- Set sapFunctions = Nothing
- Set sapFunction = Nothing
-
- err1:
- If Err.Number = 1001 Then
- MsgBox "远程调用错误,请检查SAP中是否存在函数ZBAPI_GETGLACCPERIODBALANCES,是否允许远程调用等。", _
- vbExclamation
- Exit Sub
- End If
- End Sub

另外,因为 Excel 自定义函数需要用到会计科目,从速度上考虑,把会计科目列表存放在一个工作表中,方便后续函数调用。会计科目列表调用
SAP 的 BAPI 来实现,这里直接从刚才导入的会计科目余额中提取,代码放在 account_gl_list模块 中:
- ' 模块说明:
- ' 从COASheet工作表获取公司代码下所有的会计科目清单
- ' 在UDF中,需要在会计科目的范围中循环,根据公司代码的科目清单,目的是提高效率
-
- Option Explicit
-
-
- Public Sub Generate_GL_List()
- ' 根据BS_Source的科目,产生会计科目清单,剔除重复项(如果有的话)
- ' 数据存放在GLList工作表中
-
- Dim row_count As Integer
- row_count = BSSource.UsedRange.rows.count
-
- ' 如果没有数据,则不处理
- If row_count <= 1 Then Exit Sub
-
- With GLListSheet
- ' 清除之前的数据
- .Cells.ClearContents
-
- ' 数据拷贝
- .Range("A1:A" & row_count + 1).Value = BSSource.Range("B1:B" & row_count + 1).Value
-
- ' 消除重复项
- .Range("A:A").RemoveDuplicates
-
- ' 根据会计科目排序
- .Columns("A:A").Sort key1:=.Range("A:A"), order1:=xlAscending, Header:=xlYes
- End With
- End Sub
-
-
- Public Function get_gl_count() As Integer
- '------------------------------------------
- ' 获取会计科目的数量
- ' 会计科目根据BS_Source导入的数据加工而得
- '------------------------------------------
-
- Dim count As Integer
- '因为有表头,实际的会计科目数减一
- count = GLListSheet.UsedRange.rows.count - 1
-
- get_gl_count = count
- End Function

使用一个Excel工作表作为录入界面,执行上面的会计科目余额导入程序。
当用点击【更新数据源】按钮,执行下面的代码,导入会计科目余额,至此,跟 SAP 数据交互完成。
- ' 模块说明:
- ' 从SAP系统导入会计科目余额
-
- ' Version 1.0, 2015-6-14 by Stone Wang
-
- Option Explicit
-
- Public Sub import_sap_data()
- ' 校验(input validation)
- If Range("COMPANY_CODE").Value = "" Then
- MsgBox "请输入公司代码.", vbExclamation
- Exit Sub
- End If
-
- If Range("FISCAL_YEAR").Value = "" Then
- MsgBox "请输入会计年度.", vbExclamation
- Exit Sub
- End If
-
- If Range("PERIOD").Value = "" Then
- MsgBox "请输入会计期间.", vbExclamation
- Exit Sub
- End If
-
- ' 如果没有连接到SAP,连接SAP
- If logonSuccessful <> True Then
- Call logon
- End If
-
- ' 导入会计科目余额
- Dim cocd As String
- Dim fiscal_year As String
- Dim period As String
-
- cocd = CStr(Range("COMPANY_CODE").Value)
- fiscal_year = CStr(Range("FISCAL_YEAR").Value)
- period = CStr(Range("PERIOD").Value)
-
- Call get_sap_acc_balances(cocd, fiscal_year, period)
-
- ' 根据BS_Source产生科目清单
- ' 将会计科目清单写入GLList工作表
- Call Generate_GL_List
-
- Application.Calculate
- End Sub

我打算自定义的函数叫做 AccAmount
,是对 Excel SumIfs
函数的包装和功能增强。
SumIfs
函数的语法大体如下:
SumIfs(rangeA, criteria, rangeB)
根据criteria
(条件),在rangeA
中找到相同的数据,然后将rangeB
中对应行的数据加总,并作为返回值。
增强的原因是使用 SumIfs
函数,只能处理一个科目,因为资产负债表每个数据项可能来自多个科目,所以需要对这个函数进行修改,使得能处理多个科目。
我对资产负债表的数据项数据来源,定义了一种范围表达的格式。在科目范围中,用【分号】表示分隔的科目,用【..】表示连接的科目。举例如下:
- - 1001000000..1099999999:表示 1001 开头的科目,即 1001000000 至
- 1099999999
- - 2241000000..2241999999;2703000000..2703999999:表示2241开头的科目以及2703开头的科目
有了这个定义格式,我们就实现 AccAmount()
函数:
AccAmount(rangeA, accCriteria, rangeB)
根据 accCriteria
(会计科目条件)在 rangeA
中找到对应科目,然后将rangeB
中对应行的单元格数据加总,并将汇总的数据作为返回值。
刚才所述的会计科目范围,我们需要将其分解为单个的科目,存放在数组中,代码放在 account_split 模块之中:
- '模块说明:
- '会计科目的范围用分号表示不连续的范围,用..表示连续的范围
- '会计科目范围分解出具体的会计科目,先根据分号分割,再从连续的科目中分解
- '为了提高效率,循环的时候,读取公司代码的实际科目清单
-
- ' Verion 1.1:
- ' Account_resolution函数增加了对输入参数为空的判断
-
- Option Explicit
-
-
- Private Function split_account_by_semicolon(account_range As String) As String()
- '-------------------------------------------
- ' 将科目范围根据"分号"分解,然后放在数组中
- ' 数组中每一个item, 可能是单个科目,也可能是多个科目
- '-------------------------------------------
-
- Dim acc_array() As String
- acc_array = Split(account_range, ";") ' split函数返回的数组从0开始
-
- ' 逗号分割的每一个数组元素前后可能存在空格,将空格去掉
- Dim i As Integer
- For i = LBound(acc_array) To UBound(acc_array)
- acc_array(i) = Trim(CStr(acc_array(i)))
- Next
-
- split_account_by_semicolon = acc_array
- End Function
-
-
- Private Function split_continous_account(continous_acc As String) As String()
- '将会计科目根据..进行分解
- '..表示连续的科目范围
- '如果有.., 但未找到合适科目,返回#EmptyForXXX#
-
- 'acc_count: 会计科目数量
- Dim acc_count As Integer
- acc_count = get_gl_count()
-
- Dim acc_list() As String
- If acc_count >= 1 Then
- ReDim acc_list(1 To acc_count)
- Else
- ReDim acc_list(1 To 1)
- End If
-
- Dim dot_pos As Integer ' position of double dots 双点的位置
- dot_pos = InStr(continous_acc, "..") ' 查找 ".." ,返回位置
-
- Dim lower_acc As String
- Dim upper_acc As String
-
- ' 一共需要处理三种情况:
- ' 1) 有..号,有科目被选择
- ' 2) 有..号,没有科目被选择
- ' 3) 没有..号,表示单个科目
- If dot_pos > 0 Then ' Found
- lower_acc = Left(continous_acc, dot_pos - 1)
- upper_acc = Right(continous_acc, Len(continous_acc) - dot_pos - 1)
-
- Dim account_range As Range
- Set account_range = GLListSheet.Range("A2:A" & acc_count + 1)
-
- Dim i As Integer
- Dim item As Variant
- Dim temp_acc As String
-
- i = 1 ' cocd_coa下标从1开始
- For Each item In account_range
- temp_acc = CStr(item)
- If temp_acc >= lower_acc And temp_acc <= upper_acc Then
- acc_list(i) = CStr(item)
- i = i + 1
- End If
-
- ' 确保会计科目表示按科目大小排序的
- If temp_acc > upper_acc Then
- Exit For
- End If
- Next
-
- If i > 1 Then ' i > 1表示有科目包括在其中
- ReDim Preserve acc_list(1 To i - 1)
- Else ' 表示没有科目被选择
- ReDim Preserve acc_list(1 To 1)
- acc_list(1) = "#EmptyFor" & continous_acc & "#" ' 没有找到科目,empty错误
- End If
- Else
- ReDim acc_list(1 To 1)
- acc_list(1) = continous_acc
- End If
-
- split_continous_account = acc_list
- End Function
-
-
- Public Function accounts_resolution(acc_range As String) As String()
- '----------------------------------------------------
- ' 根据科目范围,将范围分解为单个会计科目,放在数组中
- '----------------------------------------------------
-
- ' account_array()表示所有范围内科目,函数最后作为返回值
- Dim account_array() As String
-
- ' 先判断参数acc_range是否为空
- If Len(acc_range) = 0 Then
- ReDim account_array(1 To 1)
- account_array(1) = "#Empty#"
-
- accounts_resolution = account_array
- Exit Function
- End If
-
- ' 如果参数acc_range不为空,正常处理
- Dim count As Integer
- count = get_gl_count()
- If count > 1 Then
- ReDim account_array(1 To count)
- Else
- ReDim account_array(1 To 1)
- End If
-
-
- ' 先根据分号进行分解,分解后每一项表示单一科目或连续的科目
- Dim continous_acc() As String
- continous_acc = split_account_by_semicolon(acc_range)
-
- Dim i As Integer
- i = 1
-
- Dim item As Variant
- For Each item In continous_acc
- ' 再将连续的科目分解为具体的会计科目
- Dim acc_in_continuous_rng() As String
- acc_in_continuous_rng = split_continous_account(CStr(item))
-
- Dim acc As Variant
- For Each acc In acc_in_continuous_rng
- account_array(i) = CStr(acc)
- i = i + 1
- Next
- Next
-
- ' split_continuous_account()至少返回一个值
- ' 没有分解成功返回:#EmptyForXXX#, i的值一定会>=2, 所以不用判断i的大小
- ReDim Preserve account_array(1 To i - 1)
-
- accounts_resolution = account_array
- End Function

split_account_by_semicolon
函数,用于将科目范围中 有分号 的分解,并存放在一个数组之中split_continous_account
函数,用于将连续的科目分解,结果存放在数组中accounts_resolution
函数,综合上面的两个函数,对科目范围进行分解,并将结果存放在数组中将会计科目范围中的科目,循环调用 SumIfs 函数,结果加总,并作为返回值。
- ' @Author: Stone Wang
- ' @version 1.0
- ' @date: 2015-6-14
- '
- ' 模块说明:
- ' 自定义函数,获取科目在某一列的合计,该函数是对EXCEL SUMIFs函数的增强
-
- Option Explicit
-
- Public Function AccAmount(ByVal acc_range As Range, _
- ByVal acc_criteria As String, _
- ByVal sum_range As Range) As Double
-
- ' 获取account期间的余额
- ' acc_range: account range
- ' acc_criteria: account criteria
- ' sum_range: sum range
-
- Dim result As Double
-
- Dim acc_array() As String
- acc_array = accounts_resolution(acc_criteria)
-
- Dim item As Variant
- Dim current_acc As String
- For Each item In acc_array
- current_acc = CStr(item)
-
- If Len(current_acc) > 0 Then
- result = result + _
- WorksheetFunction.SumIfs(sum_range, acc_range, current_acc)
- End If
- Next
-
- AccAmount = result
- End Function

设置专门的数据源定义区,比如货币资金,设置科目范围如下:
并且将 1001000000..1099999999 所在的单元格定义一个名称为 CASH
,这样在资产负债表的货币资金行中,使用如下公式:
=AccAmount(BS_Source!B:B,CASH,BS_Source!J:J)
表示根据 CASH 单元格的科目范围(即 1001000000 至 1099999999),从 BS_Source 工作表的 B 列找到科目范围中有的科目,将相应行的 J 列数据汇总。
这样,定义了所有科目的公式之后,资产负债表就做好了。因为函数是给用户使用的,用户可以自由定义报表的各种细节,灵活性就非常好,自动化程度也高。
我曾在两个 SAP 实施项目中使用了这种方法来实现资产负债表、损益表和现金流量表。如果用户接受 Excel 作为数据展示的平台,我们可以用这个思路实现很多报表。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。