VSTO學(xué)習(xí)筆記(八)向 Word 2010 中寫入表結(jié)構(gòu)
前幾天公司在做CMMI 3級(jí)認(rèn)證,需要提交一系列的Word文檔,其中有一種文檔要求添加公司幾個(gè)系統(tǒng)的數(shù)據(jù)庫(kù)中的表結(jié)構(gòu)。我臨時(shí)接到了這項(xiàng)任務(wù),輔助相關(guān)人員完成這種文檔。
本系列所有示例代碼均在 Visual Studio 2010 Ultimate RTM + Office 2010 Professional Plus RTM x64 中測(cè)試通過
注:本次使用的數(shù)據(jù)庫(kù)為 SQL Server 2008 R2 DataCenter RTM x64
世界杯到了,首先獻(xiàn)上一張對(duì)陣表:
|
小組賽日期 |
時(shí)間 |
對(duì)陣 |
組別 |
比賽地 |
場(chǎng)次 |
|
6月11日 星期五 |
22:00 |
南非 VS 墨西哥 |
A1-A2 |
約翰內(nèi)斯堡(足) |
01 |
|
6月12日 星期六 |
02:30 |
烏拉圭 VS 法國(guó) |
A3-A4 |
開普敦 |
02 |
|
6月12日 星期六 |
19:30 |
韓國(guó) VS 希臘 |
B3-B4 |
伊麗莎白港 |
04 |
|
6月12日 星期六 |
22:00 |
阿根廷 VS 尼日利亞 |
B1-B2 |
約翰內(nèi)斯堡(埃) |
03 |
|
6月13日 星期日 |
02:30 |
英格蘭 VS 美國(guó) |
C1-C2 |
魯斯騰堡 |
05 |
|
6月13日 星期日 |
19:30 |
阿爾及利亞 VS 斯洛文尼亞 |
C3-C4 |
保羅瓜尼 |
06 |
|
6月13日 星期日 |
22:00 |
塞爾維亞 VS 加納 |
D3-D4 |
比勒陀利亞 |
08 |
|
6月14日 星期一 |
02:30 |
德國(guó) VS 澳大利亞 |
D1-D2 |
德班 |
07 |
|
6月14日 星期一 |
19:30 |
荷蘭 VS 丹麥 |
E1-E2 |
約翰內(nèi)斯堡(足) |
09 |
|
6月14日 星期一 |
22:00 |
日本 VS 喀麥隆 |
E3-E4 |
布隆馮丹 |
10 |
|
6月15日 星期二 |
02:30 |
意大利 VS 巴拉圭 |
F1-F2 |
開普敦 |
11 |
|
6月15日 星期二 |
19:30 |
新西蘭 VS 斯洛伐克 |
F3-F4 |
魯斯騰堡 |
12 |
|
6月15日 星期二 |
22:00 |
科特迪瓦 VS 葡萄牙 |
G3-G4 |
伊麗莎白港 |
13 |
|
6月16日 星期三 |
02:30 |
巴西 VS 朝鮮 |
G1-G2 |
約翰內(nèi)斯堡(埃) |
14 |
|
6月16日 星期三 |
19:30 |
洪都拉斯 VS 智利 |
H3-H4 |
內(nèi)斯普利特 |
15 |
|
6月16日 星期三 |
22:00 |
西班牙 VS 瑞士 |
H1-H2 |
德班 |
16 |
|
6月17日 星期四 |
02:30 |
南非 VS 烏拉圭 |
A1-A3 |
比勒陀利亞 |
17 |
|
6月17日 星期四 |
19:30 |
阿根廷 VS 韓國(guó) |
B1-B3 |
約翰內(nèi)斯堡(足) |
20 |
|
6月17日 星期四 |
22:00 |
尼日利亞 VS 希臘 |
B2-B4 |
布隆馮丹 |
19 |
|
6月18日 星期五 |
02:30 |
墨西哥 VS 法國(guó) |
A2-A4 |
保羅瓜尼 |
18 |
|
6月18日 星期五 |
19:30 |
德國(guó) VS 塞爾維亞 |
D1-D3 |
伊麗莎白港 |
21 |
|
6月18日 星期五 |
22:00 |
斯洛文尼亞 VS 美國(guó) |
C4-C2 |
約翰內(nèi)斯堡(埃) |
22 |
|
6月19日 星期六 |
02:30 |
英格蘭 VS 阿爾及利亞 |
C1-C3 |
開普敦 |
23 |
|
6月19日 星期六 |
19:30 |
荷蘭 VS 日本 |
E1-E3 |
德班 |
25 |
|
6月19日 星期六 |
22:00 |
加納 VS 澳大利亞 |
D4-D2 |
魯斯騰堡 |
24 |
|
6月20日 星期日 |
02:30 |
丹麥 VS 喀麥隆 |
E2-E4 |
比勒陀利亞 |
26 |
|
6月20日 星期日 |
19:30 |
巴拉圭 VS 斯洛伐克 |
F2-F4 |
布隆馮丹 |
27 |
|
6月20日 星期日 |
22:00 |
意大利 VS 新西蘭 |
F1-F3 |
內(nèi)斯普利特 |
28 |
|
6月21日 星期一 |
02:30 |
巴西 VS 科特迪瓦 |
G1-G3 |
約翰內(nèi)斯堡(足) |
29 |
|
6月21日 星期一 |
19:30 |
朝鮮 VS 葡萄牙 |
G2-G4 |
開普敦 |
30 |
|
6月21日 星期一 |
22:00 |
智利 VS 瑞士 |
H4-H2 |
伊麗莎白港 |
31 |
|
6月22日 星期二 |
02:30 |
西班牙 VS 洪都拉斯 |
H1-H3 |
約翰內(nèi)斯堡(埃) |
32 |
|
6月22日 星期二 |
22:00 |
墨西哥 VS 烏拉圭 |
A2-A3 |
魯斯騰堡 |
33 |
|
6月22日 星期二 |
22:00 |
南非 VS 法國(guó) |
A1-A4 |
布隆馮丹 |
34 |
|
6月23日 星期三 |
02:30 |
尼日利亞 VS 韓國(guó) |
B2-B3 |
德班 |
35 |
|
6月23日 星期三 |
02:30 |
阿根廷 VS 希臘 |
B1-B4 |
保羅瓜尼 |
36 |
|
6月23日 星期三 |
22:00 |
英格蘭 VS 斯洛文尼亞 |
C1-C4 |
伊麗莎白港 |
37 |
|
6月23日 星期三 |
22:00 |
美國(guó) VS 阿爾及利亞 |
C2-C3 |
比勒陀利亞 |
38 |
|
6月24日 星期四 |
02:30 |
德國(guó) VS 加納 |
D1-D4 |
約翰內(nèi)斯堡(足) |
39 |
|
6月24日 星期四 |
02:30 |
塞爾維亞 VS 澳大利亞 |
D3-D2 |
內(nèi)斯普利特 |
40 |
|
6月24日 星期四 |
22:00 |
意大利 VS 斯洛伐克 |
F1-F4 |
約翰內(nèi)斯堡(埃) |
41 |
|
6月24日 星期四 |
22:00 |
巴拉圭 VS 新西蘭 |
F2-F3 |
保羅瓜尼 |
42 |
|
6月25日 星期五 |
02:30 |
丹麥 VS 日本 |
E2-E3 |
魯斯騰堡 |
43 |
|
6月25日 星期五 |
02:30 |
荷蘭 VS 喀麥隆 |
E1-E4 |
開普敦 |
44 |
|
6月25日 星期五 |
22:00 |
巴西 VS 葡萄牙 |
G1-G4 |
德班 |
45 |
|
6月25日 星期五 |
22:00 |
朝鮮 VS 科特迪瓦 |
G2-G3 |
內(nèi)斯普利特 |
46 |
|
6月26日 星期六 |
02:30 |
西班牙 VS 智利 |
H1-H4 |
比勒陀利亞 |
47 |
|
6月26日 星期六 |
02:30 |
瑞士 VS 洪都拉斯 |
H2-H3 |
布隆馮丹 |
48 |
CMMI文檔中表結(jié)構(gòu)要求格式如下:
XX表
|
字段名 |
名稱 |
主鍵 |
數(shù)據(jù)類型(精度) |
空/非空 |
約束條件 |
默認(rèn)值 |
備注 |
|
說明 |
XX表 | ||||||
公司系統(tǒng)數(shù)據(jù)庫(kù)非常龐大,表也很多,如果一個(gè)個(gè)手工處理,那將非常麻煩,于是考慮寫一個(gè)程序,來自動(dòng)處理。
既然是生成Word文檔,我就想做一個(gè)VSTO Word插件,通過選擇的數(shù)據(jù)庫(kù)中的表,來生成表結(jié)構(gòu)。
- 創(chuàng)建一個(gè)Word 2010 AddIn項(xiàng)目:
- 在Word的Ribbon中添加一個(gè)按鈕,點(diǎn)擊按鈕后選擇數(shù)據(jù)庫(kù)、表:
測(cè)試數(shù)據(jù)庫(kù)使用的SQL Server 2008 R2 Sample Databases,可以在CodePlex上下載。
這個(gè)添加連接窗體我是仿微軟的做的,本來想找一個(gè)第三方組件,沒有找到,就自己實(shí)現(xiàn)了一個(gè),功能上有所裁剪(只支持SQL Server),夠用就好,微軟的如下:
首先選擇或輸入一個(gè)SQL Server服務(wù)器名,支持"."、"(local)"、IP地址、SQL Server實(shí)例等。本意設(shè)計(jì)的是點(diǎn)擊下拉列表時(shí)獲取局域網(wǎng)內(nèi)所有的SQL Server實(shí)例,但是始終未能實(shí)現(xiàn),若有朋友知道,請(qǐng)指點(diǎn)一下。
PS:我本機(jī)是一臺(tái)域控制器,操作系統(tǒng)為Windows Server 2008 R2 DataCenter,數(shù)據(jù)庫(kù)為SQL Server 2008 R2 DataCenter X64,獲取局域網(wǎng)內(nèi)所有的SQL Server實(shí)例的代碼為:
代碼
DataTable __dtServers = SqlClientFactory.Instance.CreateDataSourceEnumerator().GetDataSources();
foreach (DataRow __dr in __dtServers.Rows)
{
this.txt服務(wù)器名.Items.Add(__dr["InstanceName"].ToString());
}
先簡(jiǎn)單說說常用系統(tǒng)數(shù)據(jù)庫(kù)對(duì)象:
sys.all_columns
sys.tables
sys.objects
sys.key_constraints
sys.types
sys.indexes
sys.default_constraints
sys.all_objects
sys.schemas
注意SQL Server 2000、2005不受支持,因?yàn)槭褂昧艘恍┬绿匦裕匀绻獪y(cè)試代碼,請(qǐng)使用SQL Server 2008 或更新版本。
從名字上就可以看出這些系統(tǒng)表中包含的內(nèi)容,通過這些表之間的關(guān)聯(lián)我們可以取得絕大多數(shù)數(shù)據(jù)庫(kù)的元數(shù)據(jù),在某些情況下是非常有用的。
另外常用系統(tǒng)視圖:
sys.all_objects
sys.databases
sys.servers
常用系統(tǒng)存儲(chǔ)過程:
Sp_help
Sp_helptext
Sp_PKeys
Sp_rename
獲取所選擇服務(wù)器上的所有的數(shù)據(jù)庫(kù):
附加數(shù)據(jù)庫(kù):
代碼
-- Attach database template
--=====================================
IF NOT EXISTS(
SELECT *
FROM sys.databases
WHERE name = N'<database_name, sysname, your_database_name>'
)
CREATE DATABASE <database_name, sysname, your_database_name>
ON PRIMARY (FILENAME = '<database_primary_file_path,,C:\Program files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Data\your_database_name.MDF>')
LOG ON (FILENAME = '<database_primary_file_path,,C:\Program files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Data\your_database_name.ldf>')
FOR ATTACH
GO
可以選擇Windows或SQL Server驗(yàn)證,可以點(diǎn)擊【測(cè)試連接】測(cè)試一下連接是否正常。選擇或附加一個(gè)數(shù)據(jù)庫(kù)后,點(diǎn)擊確定,會(huì)獲取指定數(shù)據(jù)庫(kù)中的所有表,選擇要生成表結(jié)構(gòu)的表(默認(rèn)全選),點(diǎn)擊【確定】生成:
獲取指定數(shù)據(jù)庫(kù)中的所有表:
- 在Word中插入表格
數(shù)據(jù)庫(kù)、表選擇好了之后,剩下的工作就要在Word中處理了。【約束條件】、【默認(rèn)值】、【備注】三列忽略,
在剩下的列中,【字段名】、【名稱】(也取的字段名)、【數(shù)據(jù)類型】、【空、非空】比較好取得,只有一個(gè)【主鍵】頗費(fèi)了一番功夫。
代碼
--SELECT * FROM sys.all_columns
--SELECT * FROM sys.tables
--SELECT * FROM sys.objects
--SELECT * FROM sys.key_constraints
--SELECT * FROM sys.types
--SELECT * FROM sys.indexes
--SELECT * FROM sys.default_constraints
--SELECT * FROM sys.all_objects
--SELECT * FROM sys.schemas
--常用系統(tǒng)視圖
--SELECT * FROM sys.all_objects
--SELECT * FROM sys.databases
--SELECT * FROM sys.servers
--默認(rèn)值測(cè)試
--SELECT col.column_id,col.name,d.definition
--FROM sys.columns AS col
--INNER JOIN sys.default_constraints AS d ON col.column_id = d.parent_column_id
IF EXISTS(SELECT * FROM sys.objects WHERE type = 'P' and name = 'sp_生成數(shù)據(jù)結(jié)構(gòu)')
BEGIN
DROP PROCEDURE dbo.sp_生成數(shù)據(jù)結(jié)構(gòu)
END
GO
CREATE PROCEDURE dbo.sp_生成數(shù)據(jù)結(jié)構(gòu)
(
@TableNames SelectTables READONLY
)
AS
SET XACT_ABORT ON
BEGIN TRANSACTION
CREATE TABLE #TableNames
(
ID INT IDENTITY(1, 1),
TableName VARCHAR(200)
)
INSERT INTO #TableNames(TableName)
SELECT TableName
FROM @TableNames
DECLARE @table_owner sysname = null,
@table_qualifier sysname = null,
@table_id int,
-- quotename() returns up to 258 chars
@full_table_name nvarchar(517) -- 258 + 1 + 258
DECLARE @i INT, @Count INT, @Name VARCHAR(200)
SET @i = 1
SET @Count = (SELECT COUNT(*) FROM #TableNames)
WHILE @i <= @Count
BEGIN
SET @Name = (SELECT TableName FROM #TableNames WHERE ID = @i)
SET @table_owner =
(
SELECT s.name
FROM sys.schemas AS s
INNER JOIN sys.tables AS t ON s.schema_id = t.schema_id
WHERE t.name = @Name
)
if @table_owner is null
begin -- If unqualified table name
select @full_table_name = quotename(@Name)
end
else
begin -- Qualified table name
if @table_owner = ''
begin -- If empty owner name
select @full_table_name = quotename(@table_owner)
end
else
begin
select @full_table_name = quotename(@table_owner) + '.' + quotename(@Name)
end
end
select @table_id = object_id(@full_table_name)
SELECT col.name AS 字段名,
col.name AS 名稱,
CASE WHEN col.name IN
(
select
COLUMN_NAME = c.name
from
sys.indexes i,
sys.all_columns c,
sys.all_objects o
where
o.object_id = @table_id and
o.object_id = c.object_id and
o.object_id = i.object_id and
i.is_primary_key = 1 and
(c.name = index_col (@full_table_name, i.index_id, 1) or
c.name = index_col (@full_table_name, i.index_id, 2) or
c.name = index_col (@full_table_name, i.index_id, 3) or
c.name = index_col (@full_table_name, i.index_id, 4) or
c.name = index_col (@full_table_name, i.index_id, 5) or
c.name = index_col (@full_table_name, i.index_id, 6) or
c.name = index_col (@full_table_name, i.index_id, 7) or
c.name = index_col (@full_table_name, i.index_id, 8) or
c.name = index_col (@full_table_name, i.index_id, 9) or
c.name = index_col (@full_table_name, i.index_id, 10) or
c.name = index_col (@full_table_name, i.index_id, 11) or
c.name = index_col (@full_table_name, i.index_id, 12) or
c.name = index_col (@full_table_name, i.index_id, 13) or
c.name = index_col (@full_table_name, i.index_id, 14) or
c.name = index_col (@full_table_name, i.index_id, 15) or
c.name = index_col (@full_table_name, i.index_id, 16))
) THEN '√'
WHEN col.name NOT IN
(
select
COLUMN_NAME = convert(sysname,c.name)
from
sys.indexes i,
sys.all_columns c,
sys.all_objects o
where
o.object_id = @table_id and
o.object_id = c.object_id and
o.object_id = i.object_id and
i.is_primary_key = 1 and
(c.name = index_col (quotename(@full_table_name), i.index_id, 1) or
c.name = index_col (quotename(@full_table_name), i.index_id, 2) or
c.name = index_col (quotename(@full_table_name), i.index_id, 3) or
c.name = index_col (quotename(@full_table_name), i.index_id, 4) or
c.name = index_col (quotename(@full_table_name), i.index_id, 5) or
c.name = index_col (quotename(@full_table_name), i.index_id, 6) or
c.name = index_col (quotename(@full_table_name), i.index_id, 7) or
c.name = index_col (quotename(@full_table_name), i.index_id, 8) or
c.name = index_col (quotename(@full_table_name), i.index_id, 9) or
c.name = index_col (quotename(@full_table_name), i.index_id, 10) or
c.name = index_col (quotename(@full_table_name), i.index_id, 11) or
c.name = index_col (quotename(@full_table_name), i.index_id, 12) or
c.name = index_col (quotename(@full_table_name), i.index_id, 13) or
c.name = index_col (quotename(@full_table_name), i.index_id, 14) or
c.name = index_col (quotename(@full_table_name), i.index_id, 15) or
c.name = index_col (quotename(@full_table_name), i.index_id, 16))
) THEN '' END AS 主鍵,
ty.name + '(' + LTRIM(RTRIM(STR(col.max_length))) + ')' AS[ 數(shù)據(jù)類型(精度)],
CASE WHEN col.is_nullable = 1 THEN ''
WHEN col.is_nullable = 0 THEN 'NOT NULL' END AS [空/非空],
'' AS 約束條件,
'' AS 默認(rèn)值,
'' AS 備注,
@name AS 表名
FROM sys.all_columns AS col
INNER JOIN
(
SELECT t.object_id,
t.name AS name
FROM sys.tables AS t
WHERE t.name = @Name
) AS t ON col.object_id = t.object_id
INNER JOIN sys.types AS ty ON col.user_type_id = ty.user_type_id
SET @i = @i + 1
END
DROP TABLE #TableNames
COMMIT TRANSACTION
SET XACT_ABORT OFF
GO
這段代碼的靈感來自于系統(tǒng)存儲(chǔ)過程:sp_Pkeys,獲取一個(gè)表中的主鍵字段。輸入:sp_helptext 'sp_Pkeys'來查看源代碼,我對(duì)其進(jìn)修了修改,用在了我自己的存儲(chǔ)過程中,目的就是判斷一個(gè)字段是不是主鍵。
為了將用戶選擇的表傳遞給存儲(chǔ)過程,創(chuàng)建一個(gè)用戶自定義類型:SelectTables
代碼
BEGIN
CREATE TYPE SelectTables AS TABLE
(
Choice BIT NOT NULL,
TableName VARCHAR(200) NOT NULL
)
END
GO
然后前臺(tái)使用DataTable類型的參數(shù):
代碼{
this.__ds.Clear();
SqlConnection _cn = new SqlConnection(v_strConn);
SqlCommand _cmd = _cn.CreateCommand();
_cmd.CommandType = System.Data.CommandType.StoredProcedure;
_cmd.CommandText = "sp_生成數(shù)據(jù)結(jié)構(gòu)";
SqlParameter _p = _cmd.Parameters.AddWithValue("@TableNames", v_dt選擇表);
SqlDataAdapter _da = new SqlDataAdapter(_cmd);
_da.Fill(this.__ds);
}
存儲(chǔ)過程【sp_生成數(shù)據(jù)結(jié)構(gòu)】返回的是一個(gè)數(shù)據(jù)集DataSet,DataSet中的每一個(gè)DataTable對(duì)應(yīng)著一個(gè)物理表,下面就在Word中循環(huán)打印出來:
打印表格private void fn生成表格(System.Data.DataSet v_ds)
{
Word.Range r;
foreach (System.Data.DataTable dt in v_ds.Tables)
{
r = this.Application.ActiveDocument.Paragraphs.Last.Range;
r.MoveEnd();
Word.Table t = r.Tables.Add(r, dt.Rows.Count, dt.Columns.Count - 1);
for (int i = 1; i <= dt.Rows.Count; i++)
{
for (int j = 1; j <= dt.Columns.Count - 1; j++)
{
t.Rows[i].Cells[j].Range.Text = dt.Rows[i - 1][j - 1].ToString();
}
}
t.Rows.Add();
t.Rows[t.Rows.Count].Cells[1].Range.Text = "說明";
t.Rows[t.Rows.Count].Cells[2].Range.Text = dt.Rows[0][dt.Columns.Count - 1].ToString() + "表";
object beforeRow = t.Rows[1];
t.Rows.Add(ref beforeRow);
t.Rows[1].Cells[1].Range.Text = "字段名";
t.Rows[1].Cells[2].Range.Text = "名稱";
t.Rows[1].Cells[3].Range.Text = "主鍵";
t.Rows[1].Cells[4].Range.Text = "數(shù)據(jù)類型(精度)";
t.Rows[1].Cells[5].Range.Text = "空/非空";
t.Rows[1].Cells[6].Range.Text = "約束條件";
t.Rows[1].Cells[7].Range.Text = "默認(rèn)值";
t.Rows[1].Cells[8].Range.Text = "備注";
t.Columns[1].Width = 100;
t.Columns[2].Width = 100;
t.Columns[3].Width = 40;
t.Columns[4].Width = 100;
t.Columns[5].Width = 50;
t.Columns[6].Width = 20;
t.Columns[7].Width = 20;
t.Columns[8].Width = 20;
object title = t.Rows[1];
t.Rows.Add(ref title);
t.Rows[1].Cells[1].Range.Text = dt.Rows[0][dt.Columns.Count - 1].ToString();
t.Rows[1].Cells.Merge();
t.Rows[2].Select();
this.Application.Selection.Cells.VerticalAlignment = Word.WdCellVerticalAlignment.wdCellAlignVerticalCenter;//垂直居中
this.Application.Selection.ParagraphFormat.Alignment = Word.WdParagraphAlignment.wdAlignParagraphCenter;//水平居中
t.Rows[2].Range.Font.Bold = 2;
//感謝 sunfny 的指點(diǎn),用下面的方法設(shè)置表格單元格的背景顏色:
t.Rows[2].Shading.BackgroundPatternColor = Word.WdColor.wdColorSkyBlue;
t.Borders[Word.WdBorderType.wdBorderTop].LineStyle = Word.WdLineStyle.wdLineStyleSingle;
t.Borders[Word.WdBorderType.wdBorderLeft].LineStyle = Word.WdLineStyle.wdLineStyleSingle;
t.Borders[Word.WdBorderType.wdBorderRight].LineStyle = Word.WdLineStyle.wdLineStyleSingle;
t.Borders[Word.WdBorderType.wdBorderBottom].LineStyle = Word.WdLineStyle.wdLineStyleSingle;
t.Borders[Word.WdBorderType.wdBorderHorizontal].LineStyle = Word.WdLineStyle.wdLineStyleSingle;
t.Borders[Word.WdBorderType.wdBorderVertical].LineStyle = Word.WdLineStyle.wdLineStyleSingle;
t.Rows[1].Borders[Word.WdBorderType.wdBorderTop].LineStyle = Word.WdLineStyle.wdLineStyleNone;
t.Rows[1].Borders[Word.WdBorderType.wdBorderLeft].LineStyle = Word.WdLineStyle.wdLineStyleNone;
t.Rows[1].Borders[Word.WdBorderType.wdBorderRight].LineStyle = Word.WdLineStyle.wdLineStyleNone;
t.AllowAutoFit = true;
this.Application.ActiveDocument.Paragraphs.Add();
}
}
Word中的Range對(duì)象比較特殊,感覺比Excel的Range難操作一些。
小結(jié)
本次在通過用戶選擇一個(gè)數(shù)據(jù)庫(kù),若干表的方式在Word中打印出來這些表的表結(jié)構(gòu),其中用到了很多系統(tǒng)表、系統(tǒng)存儲(chǔ)過程,掌握這些系統(tǒng)對(duì)象還是很有必要的。其次我們練習(xí)了在Word中打印表格、控制顯示樣式的方法,也是很實(shí)用的。


浙公網(wǎng)安備 33010602011771號(hào)