整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

VBA抓取动态网页,紧盯股票主力资金

一篇文章用VBA下载一部完整小说,VBA除了可以轻松下载一部《水浒传》小说,还有什么用途?VBA获取网页信息(即爬虫技术)其用处可多了。今天介绍各位小伙用来监控的自选股票的主力资金变动的情况,愿大伙在2022年股票市场长红!也是把上期一个网友评论的内容(有些数据藏得很深,怎么找真正的地址……)回应一下。

东富的主力资金流入图

有一个理论我们会经常听到,A股的票涨涨跌跌主要是因为有大资金在活动、在操作,一些股票不断上涨是因为有主力资金不断买入,反而不断下跌是因为主力资金不断流出。喜欢做短线的,我们实时观察这些主力资金就变得很有意义,很多网站都有主力资金的数据,但是要对多支股票进行观察,则需要一个个打开网页、APP或者电脑程序查看数据,这样耗时也不能多支股票同框对比。还有一些小伙正上班,打开股票软件给老板或同事看到,总觉得怪怪的,当然这不是鼓励一些小伙上班玩股票,纯属用项目和大家一起交流学习。

用VBA就可以很轻松解决上述两个问题。大伙先看看效果吧!

点击按钮更新数据:2022年12月21日数据

完整代码如下:

Sub maincapital()

Application.DisplayAlerts = False
'循环A列数据,解析出相应股票代码
For Each cl In Range("a2:a" & Range("a2").End(xlDown).Row)
stock_code = Right(cl, 6) '取右边6位字符
Dim strText, stcok_code As String
'拼接构造网址
URL = "https://push2.eastmoney.com/api/qt/ulist.np/get?cb=fltt=2&secids=1." + stock_code + "&fields=f62%2Cf184%2Cf66%2Cf69%2Cf72%2Cf75%2Cf78%2Cf81%2Cf84%2Cf87%2Cf64%2Cf65%2Cf70%2Cf71%2Cf76%2Cf77%2Cf82%2Cf83%2Cf164%2Cf166%2Cf168%2Cf170%2Cf172%2Cf252%2Cf253%2Cf254%2Cf255%2Cf256%2Cf124%2Cf6%2Cf278%2Cf279%2Cf280%2Cf281%2Cf282&ut=b2884a393a59ad64002292a3e90d46a5&_=1641268581776"
With CreateObject("MSXML2.XMLHTTP")
    .Open "GET", URL, False
    .send
    strText = .responseText
End With

'判断是有null,解决深A股和上A股网址不同拼接问题,secids=0.是深A;secids=1.是上A。
Dim regStrTest As Object
With CreateObject("VBScript.Regexp")
    .Pattern = "null"
    Set regStrTest = .Execute(strText)
End With
If regStrTest.Count > 0 Then
'如果出现null则拼接构造一个新网址
URL = "https://push2.eastmoney.com/api/qt/ulist.np/get?cb=fltt=2&secids=0." + stock_code + "&fields=f62%2Cf184%2Cf66%2Cf69%2Cf72%2Cf75%2Cf78%2Cf81%2Cf84%2Cf87%2Cf64%2Cf65%2Cf70%2Cf71%2Cf76%2Cf77%2Cf82%2Cf83%2Cf164%2Cf166%2Cf168%2Cf170%2Cf172%2Cf252%2Cf253%2Cf254%2Cf255%2Cf256%2Cf124%2Cf6%2Cf278%2Cf279%2Cf280%2Cf281%2Cf282&ut=b2884a393a59ad64002292a3e90d46a5&_=1641268581776"
With CreateObject("MSXML2.XMLHTTP")
    .Open "GET", URL, False
    .send
    strText = .responseText
End With
End If

Rnum = cl.Row '股票名称所在行号
'利用正则表达式得到我们想要的内容,并写相应的表格
With CreateObject("VBScript.Regexp")
    .Pattern = """f62"":(.*?),"
Cells(Rnum, 2) = Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2) '主力净流进
    .Pattern = """f184"":(.*?),"
Cells(Rnum, 3) = Round(.Execute(strText)(0).submatches.Item(0) / 100, 2) '主力净比
    .Pattern = """f66"":(.*?),"
Cells(Rnum, 4) = Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2)  '超大单净流进
    .Pattern = """f69"":(.*?),"
Cells(Rnum, 5) = Round(.Execute(strText)(0).submatches.Item(0) / 100, 2) '超大单净比
    .Pattern = """f72"":(.*?),"
Cells(Rnum, 6) = Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2)  '大单净流进
    .Pattern = """f75"":(.*?),"
Cells(Rnum, 7) = Round(.Execute(strText)(0).submatches.Item(0) / 100, 2) '大单净比
    .Pattern = """f78"":(.*?),"
Cells(Rnum, 8) = Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2)  '中单净流进
    .Pattern = """f81"":(.*?),"
Cells(Rnum, 9) = Round(.Execute(strText)(0).submatches.Item(0) / 100, 2) '中单净比
    .Pattern = """f84"":(.*?),"
Cells(Rnum, 10) = Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2)  '小单净流进
    .Pattern = """f87"":(.*?),"
Cells(Rnum, 11) = Round(.Execute(strText)(0).submatches.Item(0) / 100, 2) '小单净比
    .Pattern = """f64"":(.*?),"
Cells(Rnum, 12) = Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2) '超大单流入
    .Pattern = """f65"":(.*?),"
Cells(Rnum, 13) = Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2) '超大流出
    .Pattern = """f70"":(.*?),"
Cells(Rnum, 14) = Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2) '大单流入
    .Pattern = """f71"":(.*?),"
Cells(Rnum, 14) = Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2) '大单流出
    
End With
Next
Application.DisplayAlerts = True
End Sub

这个项目用到的几个重要知识:

  1. 获取动态网页加载数据的真正网址;
  2. 使用CreateObject("MSXML2.XMLHTTP")对象获取网页信息,基本框架可以参考用VBA下载一部完整小说;
  3. 使用CreateObject("VBScript.Regexp")正则表达式对象,处理网页信息并写入表格;
  4. 点击按钮调用函数

获取动态网页加载数据的真正网址

我们在目标网页点击右键,并点击“查看网页源代码”后,当使用cttl+f键查看我们想要获取的信息进行查看(这里我输入主力净比数据-42.76),发现并没有相关的数据。

在源代码网页同时按cttl+f键查看

通过这个方法基本可以判断目标网页的部分数据是使用动态加载的方式。简单的动态加载数据,可以通过以下两步获取真正的网址:

第一步:打开浏览器控制台。演示使用的浏览器是chrome,按下F12键打开浏览器控制台,再次刷新网页,在控制台找到并点击扩大镜小按钮,打开search对话框,这里输入想找的数据(这里我输入主力净比数据42.76)后,按下回车键或输入框旁边的刷新按键,就会弹出一个“get”字符及一些类似网址的内容,点击弹出的内容,右下面对话框会弹出相应的内容(对话框的菜单有Headers,Preview,Response……)

图中主力净比数据为-42.73和在输入框的数据不一致,是因为资金数据动态变化了

第二步:找到加载数据的网址。点击Headers可以看到Resquest URl字符,后面网址就是加载数据真正的网址,复制网址在浏览器打开,我们可以看到相应的数据内容。获得这网址后,就可以通过VBA访问这个网址获取相应的数据,按下来的工作就好办了。

目标数据的网址


使用CreateObject("MSXML2.XMLHTTP")对象获取网页信息

stock_code = Right(cl, 6) '取右边6位字符
Dim strText, stcok_code As String '
'拼接构造网址
URL = "https://push2.eastmoney.com/api/qt/ulist.np/get?cb=fltt=2&secids=1." + stock_code + "&fields=f62%2Cf184%2Cf66%2Cf69%2Cf72%2Cf75%2Cf78%2Cf81%2Cf84%2Cf87%2Cf64%2Cf65%2Cf70%2Cf71%2Cf76%2Cf77%2Cf82%2Cf83%2Cf164%2Cf166%2Cf168%2Cf170%2Cf172%2Cf252%2Cf253%2Cf254%2Cf255%2Cf256%2Cf124%2Cf6%2Cf278%2Cf279%2Cf280%2Cf281%2Cf282&ut=b2884a393a59ad64002292a3e90d46a5&_=1641268581776"
With CreateObject("MSXML2.XMLHTTP")
    .Open "GET", URL, False
    .send
    strText = .responseText
End With

'判断是有null,解决深A股和上A股网址不同拼接问题,secids=0.是深A;secids=1.是上A。
Dim regStrTest As Object
With CreateObject("VBScript.Regexp")
    .Pattern = "null"
    Set regStrTest = .Execute(strText)
End With
If regStrTest.Count > 0 Then
'如果出现null则拼接构造一个新网址
URL = "https://push2.eastmoney.com/api/qt/ulist.np/get?cb=fltt=2&secids=0." + stock_code + "&fields=f62%2Cf184%2Cf66%2Cf69%2Cf72%2Cf75%2Cf78%2Cf81%2Cf84%2Cf87%2Cf64%2Cf65%2Cf70%2Cf71%2Cf76%2Cf77%2Cf82%2Cf83%2Cf164%2Cf166%2Cf168%2Cf170%2Cf172%2Cf252%2Cf253%2Cf254%2Cf255%2Cf256%2Cf124%2Cf6%2Cf278%2Cf279%2Cf280%2Cf281%2Cf282&ut=b2884a393a59ad64002292a3e90d46a5&_=1641268581776"
With CreateObject("MSXML2.XMLHTTP")
    .Open "GET", URL, False
    .send
    strText = .responseText
End With
End If

上面代码的说明:

1、使用right(目标字符串,字符个数)函数获取目标字符串从右边数起第几个字符。

2、做两次网址请求是因为深A股和上A股的数据网址是有区别,网址的参数“secids=0.+ 股票代码”是深A;“secids=1.+股票代码”是上A。如果人为对每支股票判断是上A还深A会很复杂,所以使用正则表达式,对请求数据内容出现“null”字样的网址,则更换网址参数。如下图:

上A网址请求结果

深A网址请求结果


使用CreateObject("VBScript.Regexp")正则表达式对象获取数据

For Each cl In Range("a2:a" & Range("a2").End(xlDown).Row)
……
Rnum = cl.Row '股票名称所在行号
'利用正则表达式得到我们想要的内容,并写相应的表格
With CreateObject("VBScript.Regexp")
    .Pattern = """f62"":(.*?)," 'VBA的英文的双引号
Cells(Rnum, 2) = Round(.Execute(strText)(0).submatches.Item(0) / 100000000, 2) '主力净流入
    .Pattern = """f184"":(.*?),"
Cells(Rnum, 3) = Round(.Execute(strText)(0).submatches.Item(0) / 100, 2) '主力净比
    .Pattern = """f66"":(.*?),"
……

上面代码的说明:

1、Range("a2").End(xlDown)是表示定位从A2单元往下最后一个不空值的单元格。

2、cl.Row是表示单元格的行数,Range("A1").Row,Cells(1, 1).Row都可以获取单元格行数,列值则是Range("A1").Column和Cells(1, 1).Column。

3、.Pattern = """f62"":(.*?)," 是正则表达式(网页的内容是:"f62":-15043563520.0),VBA的英文的双引号用正则表式表示则是两个双引号,即是""。"f62":后面数据就是主力净流入的数据,用(.*?)表示。再用.submatches.Item(0)得到目标数据,这个数据是以元为单位,网页显示的是亿,所以要/100000000。

4、Round(目标数据,小数点位数)是取多少位小数的方法。


点击按钮调用函数

Private Sub CommandButton1_Click()
Call maincapital '调用函数
End Sub



在这总结一下VBA抓取数据主要步骤:

分析网站->>分析网页数据->>处理网页数据->>储存网页数据

欢迎大家评论及提意见,相互学习,提高效率,创造价值。

TML <script> 标签被用来向 HTML 中插入 VBScript。


HTML 中的 VBScript

如需在 HTML 中插入 VBScript,脚本必须写在标准的 <script> 和 </script> 标签之间。

在 <script> 标签中,请使用 type 属性来定义脚本语言 "text/vbscript":

<html>

<body>

<script type="text/vbscript">

...

</script>

</body>

</html>

IE 将解释和执行 <script> 和 </script> 之间的 VBScript 代码。


VBScript 输出

当 VBScript 被用在 Web 服务器上的 ASP 页面时,语句 response.write() 产生输出。

当我们使用 Internet Explorer 来测试 VBScript,我们使用 document.write() 来产生输出:

实例(仅适用于 Internet Explorer)

<html>

<body>

<script type="text/vbscript">

document.write("Hello World!")

</script>

</body>

</html>

在上面的实例中,浏览器输出 "Hello World!" 到 HTML 页面。

VBScript 不应该被用作客户端脚本语言!

在这里,我们使用仅适用于 IE 的 VBScript 的用于学习。

能是将一个html 表格变成 Microsoft Excel 格式的最快方法。ContentType 属性通知
浏览器数据要被格式化为何种格式,在这里我们要的格式是Microsoft Excel。当浏览器看到这个属性的值是Excel时,它就提示用户保存或打开这个文件。如果用户选择打开文件,
就启动了Excel并在其中观看数据。为使其工作正确,必须在向Response对象写入任何内容之前设置ContentType 。此语法的例子如下:
   Line 1: 〈 %@ LANGUAGE="VBSCRIPT" % 〉
   Line 2: Response.ContentType = "application/msexcel"
   Line 3: % 〉
   点击这里可以得到有关ASP的Response 对象的ContentType属性的更多信息。
   当我试图用Internet Explorer 4.x.测试时发现了一个问题,在Microsoft文章 Q185978曾经提到过。 这篇知识库文章的内容可以概括如下:
   “如果Internet Explorer 与一个动态生成Word、 Excel或其它活动文档的Web服务器
资源相连接时,Internet Explorer会为此资源发出两个GET 请求。第二个GET 通常没有ses
sion 状态信息、临时 cookies或者已经为客户指定的证明信息。这个错误可能影响到任何
寄宿在Internet Explorer 结构窗口内的本地服务器(EXE) 的活动文档应用程序。它在ISAP
I、 ASP或 CGI 应用程序中发生最为频繁,它们校验HTTP "Content Type" 头文件以识别所
安装的应用程序”。
   因此如果你尝试使用session 变量或 cookies, 并使用IE4,就有可能遭遇到这个错
误。经证实,在IE5中这个问题已经得到解决。
   一个用逗号分隔开的值文件是将web页面输出到Excel可读格式的第二种选择。这种格
式比ContentType 属性有更大的灵活性。相对于其它方法,CSV还有两个优势:首先,不需
要任何客户机或服务器上的 软件去创建它,第二,文件通常要比一个Excel 文件小。
   CSV格式的定义如下:逗号分隔列,回车分隔行。逗号作为分隔符, 也会与包含逗号
的 域(如,234)引发一个问题; 这会在将要创建的行中导致一个额外的列。这个问题也
很容易矫正, 方法是在每个结尾处用逗号将域封闭起来。
   在提供的例子中把 CreateCSVFile()函数过一遍,就能了解CSV文件是如何创建的。
   Line 1: strFile = GenFileName()
   Line 2: Set fs = CreateObject("Scripting.FileSystemObject")
   Line 3: Set a = fs.CreateTextFile(server.MapPath(".") & "" & strFile &
Line 4: ".csv",True)
   Line 5: If Not oRS.EOF Then
   Line 6: strtext = chr(34) & "Year" & chr(34) & ","
   Line 7: strtext = strtext & chr(34) & "Region" & chr(34) & ","
   Line 8: strtext = strtext & chr(34) & "Sales" & chr(34) & ","
   Line 9: a.WriteLine(strtext)
   Line 10: Do Until oRS.EOF
   Line 11: For i = 0 To oRS.fields.Count-1
   Line 12: strtext = chr(34) & oRS.fields(i) & chr(34) Line 13: & ","
   Line 14: a.Write(strtext)
   Line 15: Next
   Line 16: a.Writeline()
   Line 17: oRS.MoveNext
   Line 18: Loop
   Line 19: End If
   Line 20: a.Close
   Line 21: Set fs=Nothing
  Line 22:Response.Write("Click〈 A HREF=" & strFile & ".csv 〉Here〈 /A 〉
   Line 23: to get CSV file")
   第一行调用GenFileName() 函数创建一个唯一的文件名,有关GenFileName() 函数将
在稍后讨论。
   第2行到第4行,用FileSystemObject 对象和CreateTextFile函数将要写入的文本文
件。在这个例子中, 所写入的文件与源文件在同一个路径下,在实际工作中,你也许想要
创建一个单独的路径存储这些文件。
   第5-9行产生第一行的标题。因为报告通常都是相同的,我就把列名的代码固定下来,
虽然也有可能读 数据库的列名并使用它们。注意我在各个域中是如何包含逗号的。使用Wri
teLine 函数将它们与一个回 车一起发送到文件中。
   第10行到18行在记录集中循环,用引号给每个域做出标志,后面跟着一个逗号。然后W
rite函数将每个 域发送到文件。WriteLine 用回车结束每一行。
   最后几行关闭文件、释放对象、在页面上放置一个链接以便能够找回它。
   当你点击生成的链接时,就会被提示保存或打开。如果选择打开,文件就在Excel 中
打开(假设计算机 上已经安装)。如果选择了保存,就将这个文本文件保存到存储设备上
并将它输入各个应用程序中。
   我所讨论的最后一种方法是用Microsoft Excel 对象创建一个实际的Excel(.xls ) 文
件。要使用这些对象要求在Web 服务器上安装Excel。使用这些控制可以对格式化有更多的
控制(如字体、颜色等), 并允许你进行一切在真正的Excel 应用程序中可以进行的操
作。一定要监视你的服务器的性能,因为 Excel 可能成为一个相当大的对象并对性能造成
冲击,这取决于你如何使用它以及服务器有多忙。
   我发现在Excel 对象上得到更多信息的最快最简便的方法是使用Visual Basic对象浏
览器,观看对象 并使用上下文敏感帮助来得到更多细节。使用这个对象浏览器时:启动Vis
ual Basic, 创建一个工程文件, 增加一个对Microsoft Excel对象库的引用。在 View 菜
单下,可以选择一个对象浏览器然后指定Excel 库,看到所有可用的对象。按 F1可得到当
前标题的上下文敏感帮助。
   在所提供的样本中把CreateXlsFile() 函数过一遍,就可以看到如何创建一个Excel文
件。 基本步骤与 创建 CSV文件的基本相同,只是所创建的是一个Excel工作表。
Line 1: Dim xlWorkSheet
Line 2: Dim xlApplication
Line 3: Set xlApplication = Server.CreateObject("Excel.Application")
Line 4: xApplication.Visible = False
Line 5: xlApplication.Workbooks.Add
Line 6: Set xlWorksheet = xlApplication.Worksheets(1)
Line 7: xlWorksheet.Cells(1,1).Value = "Year"
Line 8: xlWorksheet.Cells(1,1).Interior.ColorIndex = 5
Line 9: xlWorksheet.Cells(1,2).Value = "Region"
Line 10: xlWorksheet.Cells(1,2).Interior.ColorIndex = 5
Line 11: xlWorksheet.Cells(1,3).Value = "Sales"
Line 12: xlWorksheet.Cells(1,3).Interior.ColorIndex = 5
Line 13: iRow = 2
Line 14: If Not oRS.EOF Then
Line 15: Do Until oRS.EOF
Line 16: For i = 0 To oRS.fields.Count-1
Line 17: xlWorksheet.Cells(iRow,i + 1).Value = oRS.fields(i)
Line 18: xlWorkSheet.Cells(iRow,i + 1).Interior.ColorIndex = 4
Line 19: Next
Line 20: iRow = iRow + 1
Line 21: oRS.MoveNext
Line 22: Loop
Line 23: End If
Line 24: strFile = GenFileName()
Line 25: xlWorksheet.SaveAs Server.MapPath(".") & "" & strFile & ".xls"
Line 26: xlApplication.Quit ' Close the Workbook
Line 27: Set xlWorksheet = Nothing
Line 28: Set xlApplication = Nothing
Line 29: Response.Write("Click 〈 A HRef=" & strFile & ".xls 〉Here〈 /A 〉
to Line 30: get XLS file")
   第1行和第2行,确定所使用的 Excel对象的维数。
   第3行,创建Excel对象。同样,为了工作正确,web服务器上也必须有Excel。
   第4行,将Excel的可见性设置为false,这样它就没有界面了。
   第5行和第6行,增加一个容纳工作表的工作簿,然后将当前工作表设置成第一个工作
表(这是Excel 在默认状态下创建的)。 还可以用 Worksheet对象的Add 函数增加一个新的
工作表, 这就允许你的 Excel 文件中有多个工作表。
   第8-12行,创建工作表的标题。在这个例子中,我们把每个单元的值都设置成适当的
标题,而且把内部 颜色设置成兰色。你还可以用Range对象同时修改多个单元。
   第13-23行,提供从记录集装载所有数据的循环。因为第一行中包含标题,我就在电子
数据表的 第二行开始数据。里面的 For循环把每一列装载到行中,并把内部颜色设置为绿
色。外部循环则为 每一行在记录集中进行循环。
   第24行, 通过调用GenFileName()函数,与CSV用同样的函数来创建唯一的文件名。
   第25行,进行电子表格的实际保存。可以将表格存储为 Excel中指定的多种格式。
   下面的3行进行对象的整理。作为一个好的ASP程序员,就一定要整理所有的对象。
   最后,我把到 Excel文件的链接放在页面上以便下载。
   我创建了一个样本,对以上讨论过的每个技巧进行示范。要安装样本,只需要把所有
的文件复制到服务器上,用 main.html 启动应用程序。在服务器上需要有 Excel以使用"Na
tive Excel" 选项。 样本使用一个Access数据库 (无DSN链接)来存储销售数据。
   你可以选择一年或一个地区进行销售报告。最后的选项是你希望如何返回数据。可以
看到以下的屏幕映象:
<p align="center">
   下面的表格中是对样本中提供的所有文件的描述。
文件名 描述
DSN-SQL.asp 包含无DSN链接字符串
adovbs.inc 包含ADO常量
TestDB.mdb 包含销售数据的一个Access97数据库。包含的销售表格有3个域:year--Tex
t, region--Text,sales-amt--numeric
main.html 本文件创建画面的框架并装载初始页
welcome.html 本文件只在第一次创建结果通常所在的画面框架时使用
request.html 包含一个表单,用来收集用户的选择来建立报告
runquery.asp 应用程序的内脏。本文件建立SQL声明、确定客户机如何请求将被返回的数
据、执行SQL并按照请求返回数据
   大部分代码都相当容易理解。但是我还是要讨论runquery.asp 文件中的一些函数。我
已经演示过如何创建CSV和Excel 文件。
   GenHTML()函数建立一个被请求数据的HTML表格。这个函数既用来作为HTML返回也用于
ContentType请求。为了 ContentType请求工作,你要注意 Response.ContentType = "appl
ication/msexcel" 是将要执行的最初几行之一。
   GenFileName()函数使用系统日期建立文件名的第一部分。这个文件名将是唯一的,这
样当你试图存储 文件时就可以避免许多麻烦。扩展名( CSV或XLS )在存储文件时应用,这
样就允许同一个函数产生两种类型的文件。
   BuildSQL()函数使用表单变量来建立一个SQL声明,与用户的请求相匹配,并将其返回
调用者。
   Recordset在脚本的最顶部被打开,因为它对于所选择的显示类型是独立的。recordse
t处理从BuildSQL()函数调用生成的SQL声明,使用一个到Access 97的无DSN链接。
   〈 BODY 〉标记中包含的代码仅仅是两个 "if….then" 声明,确定用户所要求的显示
方法。 if声明分流到生成正确返回类型的函数,该返回类型是基于用户的"ReturnAS" 选
择。接着清除链接和记录集对象。
   注意: 这个样本没有涉及到用户下载web服务器上创建的文件之后,对这些文件的维护
问题。我建议 这种维护要基于一段时间,时间到期后就删除这些文件。 我不主张把移走这
些文件的负担转嫁到客户身上(通过页面上的链接),因为他们很容易忘记这些事情。


   结论
   本文演示了将数据输出到一个Excel可读格式的三种方法。 我相信根据用户的不同需
要,这三种方法都有其可用之地。如果你愿意快速但不漂亮地输出到Excel,就用ContentTy
pe好了。如果你想要一个格式有限但能够装载到许多不同应用程序中的文件,那么CSV格式
适合你。如果你更喜欢包含完整格式、图标或特殊Excel功能,那么创建一个完全的Excel电
子表格是适合的途径。 但愿这些方法能帮助其他程序员满足客户的要求或者至少帮助你选
择正确的途径。