终于有家了!

发布新日志

  • 全程测试,从需求到设计到代码,集中人力来解决每个环节遇到的问题

    2009-12-17 16:37:23

    去年,我们要让软件开发团队管理上台阶。

    我们由于处于企业管理软件开发领域,而对日外包大部分接的单子都是管理软件之类的单子,但是人家的项目管理、进度、质量都比我们好,如果他们再配合管理咨询公司作为合作伙伴,再加上大规模的服务呼叫中心,像我们之类岂有出路?

    于是我们就想到了引入对日外包的开发过程管理。

    大家一想起对日外包,就想到了大量的文档和大量的代码工人,想到了详细设计说明书甚至到函数级、伪代码级。

    要不要引入的时候,我们内部也做了争论。觉得对日外包,人家接的单子额比国内客户大,所以也能招聘大规模的员工,而且对日外包,日本人是很理性的看待项目周期的(国内客户要求一个月开发完上线),而且日本人都做了半年到一年的调研和设计分析(国内调研几乎只是一个上午,坐在一起瞎聊,根本不成方法)。所以对日外包不适合咱们。咱们没有钱招聘一定数量的人(即使我们只需要普通员工,而不是人才,我们也没多余的钱),当然我们也无法分离那么多专职的项目管理、开发、测试、文档、配置管理岗位。我们的客户对于软件的认知决定了我们无法在调研、设计上下太多功夫(单子额就那么大,客户认为软件就值那么多钱,当然无须对软件生产各个环节进行重视)。

    不过,我还是坚持进行引入。是骡子是马,咱们拉出来遛遛。还没遛,就说不行。这不是小时候的小马过河了么?

    引了进来,合作伙伴给我们派了一位质量控制部的人员。

    一入手,发现有个很关键的问题,方法的源头。

    因为对日外包,都是接单生产,主要是编码、测试,保证生产进度和质量要求。但编码之前的所有环节,对日外包公司并不清楚。他们只知道拿人家给的设计书开始coding,设计书怎么来的,前面环节产生过哪些文档,不清楚。

    幸亏我们过去有系统的调研方法,从调研描述现状、然后分析优化的组织结构、工作流程、考核报表、岗位职责四大块来描述需求。客户优化后的流程、工具中包含手工纸张信息、EXCEL信息、软件信息。

    把这些转变为软件中的功能、权限、报表也一气呵成。组织结构和岗位职责决定了功能点和功能权限、工作流程决定了软件流程、工作流程中使用的纸张信息、 EXCEL信息、软件信息就是数据输入,报表就是数据输出。这就是一个企业管理软件的四大块:组织权限、输入、处理流程、输出。

    所以说,企业管理软件的开发是有方法和规律的,比较容易,就连最难的调研和需求管理也有方法。所以企业管理软件的开发,现在主要集中在大规模开发团队的组织、任务调度、人员培训(大规模的开发,必然需要的是一般素质的人员,而非高级人才,否则不可能有那么多资金来实现大规模开发)、大规模开发团队的质量和进度(人多了,各个层次各个水平的人都有,理解都不同,如何保证质量和进度是很关键的,否则很容易项目预算失控。一般素质的人多了,对于管理的要求是很高的,很容易成为乌合之众,只消耗不产出)。我特羡慕KFC,不管我们在大江南北哪里,迟到的KFC是一样的口味和品质,享受的服务和环境也差不多,这很难。那么多店,而且都是授权店而非自主经营店,那么多一般员工,而且员工流失和临时员工也非常多,居然能保证一样,管理水平实在了得。所以我经常学习 KFC和丰田,如何使一般员工大规模配合工作。

    对于企业管理软件开发过程中的文档,我们一般有需求分析说明书,其编写格式和思路,和我们的需求调研方法一致,也就是说,我们的需求调研的结果,落实到纸面,就有需求分析说明书,另外还有一份需求调研报告,是偏向于项目过程叙述的。

    需求分析说明书回来,研发部内部会进行大家一起学习理解,然后讨论。

    讨论主要由:需求调研人、业务组组长、测试组组长来参加。一个个的过流程。因为在需求调研期间,去的只是调研人,可能有想不全的地方。如果这样就直接进行开发,无疑会有很多漏洞。这样给开发、测试,都带来了返工修改,给项目管理也带来了项目进度、任务分配的调整,计划的打乱也间接影响了质量管理。

    根据大家讨论补充后的需求分析说明书,就比较容易得到我们下面环节的文档。

    首先我们会出功能点文档。

    我们会把需求分析说明书中的业务功能都列出来清单,属于组织结构建立、组织角色、权限分配、登陆验证、基础数据维护之类的都归类到系统功能中。系统管理,各个企业管理软件差不多,我们又有公共的系统管理模块,就不需要重新发明轮子了。所以,我们主要重点是分析业务功能。

    根据需求分析说明书中的每个流程,都先提出来成为一个功能点。然后针对现在整理出来的功能点,再一个个对照流程,如果这个流程复杂,就拆分,把这个功能点拆成几个复杂性和预估工作量差不多的功能点。经过这样的拆分,就形成了最终的功能点文档。

    而功能点之间,根据上述方法的拆分,就形成了功能群。

    功能点就成为功能权限控制的最小单位。功能群就成了软件菜单中的一项。几个相关联的功能群就成为了一个业务子系统。

    就这样的方法,使子系统-功能菜单-功能点(可能是某个功能窗口上的功能按钮)三级分开,与组织结构-员工-角色-用户-权限结合。一个软件,未来会成为什么样子,大框架就出来了。

    做功能点清单,就类似于跑马圈地,这个项目到底多大,我先把项目边界框起来,而不要让这个项目无边无界,那自然也不会有可落实的项目进度和项目管理。知道了项目最大做到多大,就能决定是亏是赚,是做还是不做,能不能做了,有可用的时间和人力来做否。

    然后,我们会根据功能点清单,为每一个功能进行优先级的标示。我们通常会把优先级分为三级。这就意味着一个项目,大致分为三个阶段。一级是必须要做的,即使延期也要做,必须调度多加人手多加班也要完成。一级做完后,如果有时间,就把二级完成。如果时间超期,有适度的尽量去完成二级,可以延期,但也要根据预算和时间。如果适当延期也无法完成,我们会给客户去上线实施,变实施边并行开发,使实施团队和开发团队进行并行工作。所以,二级也是重要的功能。三级就是如果时间用完,三级的功能就要舍弃掉不开发。

    一般是,按功能的重要性来划分优先级,我们在之前已经讲过,我们调研需求的时候,就把常用业务和异常业务分开,把每天做的业务,和每周、每月、每季、每年做的业务分开。几个结合特别紧密的,互相关联的,我们也会把他们划分在同一个优先级,需要单独开发的基础数据维护界面,我们也会放在同一个优先级。这样,只要我们项目到期,或者我们迫于竞争突变,我们会随时推出一个可以完整使用的系统。虽然这个系统可能功能简陋,但可以完整处理整个常用业务流程,而不会造成中断,无法处理下去。

    很多开发团队,开发的方法是先字典功能,然后是业务功能,然后是报表。这种开发方法就导致了很多业务系统,客户上线使用了,光输入数据,没有输出,业务系统成了一个闷葫芦,用户得不到使用价值,可能只是减轻了工作量,加快了工作效率,提高了部门间的自动配合。更有甚者,业务功能开发了一半,到处都是断路,走不下去,无法成为一个完整的系统,就是个半成品,上不上下不下,无法适应竞争变化。

    我们开始针对功能点清单编写我们的功能设计说明书。

    我们是按照优先级来编写功能设计说明书的。我们并不会把功能设计说明书都编写完毕后才开始编码。而是,我们先把优先级为一的详细功能设计编写出来,就开始开发。二级的功能编写会在开发人员进行一级功能编码的时候并行。

    功能详细设计说明书由业务开发组的组长来编写,属于系统类功能或公共类的功能,都归给公共代码人员来编写,需要复杂的算法,高性能,高安全,高数据量,需求一直未确定最终解决方案的未来未知变化的接口,也都由公共代码人员来编写。所以,一个开发团队,有高技术的公共代码人员,有深刻理解业务的业务开发组组长,有普通的coding人员。业务开发组的组长一般由熟悉客户业务,编码经验较多但技术能力一般、踏实细心负责适合团队管理的人担任。

    功能设计说明书,根据每个功能点详细展开描述。一般一个功能点由一个EXCEL文档来详细描述。

    EXCEL文档第一个sheet中是版本信息,每次修改都有变更记录。第二个sheet是页面布局。我们通常会用PPT或开发工具建立个界面草图,然后贴上去。第三个sheet是页面上面的每个字段的说明,如默认值、不可为空、输入约束、主键唯一、输入长度、参照录入等等。第四个sheet,如果有必要,可以用VISIO画出业务流程图。第五个sheet是关于运行要求,如易用性、安全性、性能、数据量、并发性,这几个特性都分为高中低三个等级。另外,对运行的操作系统、内存都做了最低要求。一个功能,必须考虑它的用户的计算机水平,否则功能很实用,但就操作不习惯,客户非要改成客户习惯的方法,我们经常会面临这样的要求。与其那样让客户赶着我们,还不如我们自己提前在设计的时候就要求我们自己。我们在需求调研的阶段会调研客户的信息化现状,如IT维护人员能力,信息化应用能力,客户老板对信息化认知理解,最终用户信息化操作能力。

    我经常看见不少客户没有IT维护人员,不知道有服务器这一说法,更不知道什么是SQLSERVER,也不知道备份。对于信息化的理解就是上套软件,装个 XP还不知道WINDOWS要升级(很多上网的机器连XP SP2都不装,什么防火墙放木马的都没有),就知道装个瑞星杀毒,天天抱怨机器超慢。一看机器,也确实是老了,2002年的机器,128M内存。而且操作者打字和鼠标都不灵光,让他双击或鼠标右键,他根本不理解。跟他电话里说打开某个功能菜单,他很莫名其妙电脑中怎么会有菜单?如果你的软件是基于.net 的,他连.net 运行时都不知道到哪里去下载。所以我们的软件需要在什么硬件上什么基础软件上运行,数据量多大仍然可以运行流畅,我们的软件要达到的易用操作程度,要达到的易用维护程度等等,我们必须在设计期考虑到。

    很多做软件开发的,尤其不注重这方面,所以我在这里重点强调啰嗦一下。大家不要耻笑用户,大家的工资都是他们给咱们的,而不是老板。用户不是计算机高手,他们不懂双击、滚动、鼠标右键很正常。我们的衣食父母,我们要好好对待。我们不要和我们的钱作对。

    EXCEL功能设计文档到此,其实还缺一块。就是数据操作流程。

    我们先不编写数据操作流程。我们会先交给测试组的人员来校验这个功能点的详细设计,是否和需求流程和需求要求吻合,不符合的地方就整改。

    整改后的功能设计文档,算是和需求说明文档一致,设计正确。这时候才涉及到具体的实现说明。

    我们会让公共代码人员出界面输入输出和业务流程图中整理出数据结构。我们为什么不让业务开发组的组长来整理表结构,就是由于业务开发组的组长熟知业务却对技术并不精通。数据结构很影响未来的性能、扩展,所以应该由公共代码人员来设计表结构,并且建立视图和存储过程。

    公共代码人员为了考虑性能和扩展,表结构的设计可能就被打散成多个表,而不是业务开发组长自然理解的存储结构。所以公共代码人员建立了视图,保证在视图的层面上让业务代码开发组的人看到的是一个自然的业务实体数据结构,根本无须理解内部的表结构之间的关联关系。而且有存储过程来保证如何无须知道表之间的关联关系就可以增删改数据。

    从这种分工配合来看,我们采取的是从后到前的开发方法。先有数据层,有基础表结构、视图、存储过程,然后基于视图和存储过程进行业务流程代码开发,最终由普通的业务开发人员进行界面拖控件绘制界面。所以业务开发人员既不熟悉业务,也不熟悉技术。

    公共代码人员把设计完毕的数据结构交给业务开发组组长,组长来编写每个功能的数据增删改查操作文档。增加这部分文档到EXCEL中,成为第六个sheet。
    我没有研究过测试驱动。我一直提倡的是全程测试,从需求到设计到代码到文档到打包,都要经过测试。只有每个环节都能保证正确,结果才会正确。如果到了代码编写完后才发现了不对,甚至是需求一开始就理解的不对或有矛盾流程,这就糟糕了。许多人喊需求总变,项目进度无法保证,不仅仅是没有配备需求调研人、业务开发组组长、测试人,更是研发流程方法上有问题,没有采取全程测试。

    文档编写完毕一个整块(不是全部的一级功能编写完毕后),我们就会交付给业务开发组去开发。具体开发人员任务安排,由业务开发组组长来决定。需要由公共开发人员来开发的,业务开发组组长都会根据自己的开发计划和公共开发人员的任务列表(我们用需求管理系统来安排每个人的开发任务),告知公共开发人员预期的实现完毕时间。

    这样,公共开发和业务开发在并行,设计编写和功能开发在并行,设计和设计测试在并行,代码和代码测试在并行(我们采取的是版本管理和每日构建)。这样的情形就跟流水线工作一样,颇有点像丰田的流水线生产,一旦发现某个环节出现问题,理解集中人力来解决,而不会让这个问题的这个人延期钻牛角尖,否则,所有的项目进度管理都成了一句空话。没有了实质的进度,也就没有了实质的项目预算管理。那到底能不能赚钱,真成了一个鬼才知道的问题。

    很多朋友在开发当中没有写过文档,一旦有想法要正规化研发管理,就动辄要求全程文档,这文档,那文档,把开发人员累的,最后产品质量和产品进度都没有保证。一看试验失败,就全盘否定编写文档,再回归到一无所有的状况。真是走两个极端。

    希望这篇文章能够给大家以平和的心态看待编写文档。我们并不是为了正规才编写文档,我们写的每一个文档都有作用。我们也在力求能少写就少写,根据团队的、客户的磨合理解共识程度,哪个文档或哪个环节不需要写,我们就砍掉。

    我们并不在乎正规不正规,我们也并不在乎我们看上去很美,那没有用。我们只是商业开发,我们要的是可控,在有限的人力资源、合同额、合同周期内交付出客户认可的质量产品(不是高质量,是客户能接受的质量,我们从来不为没有利益回报的东西多付出)。

    来源:huawen的blog

  • QTP中DataTable操作大全

    2009-03-03 12:57:42

      序曲

       假设现在有一个Excel文件:D:\data.xls,里面的具体内容如下:有两个Sheet,第一个叫Login,第二个叫InsertOrder;

       当前QTP的Test中有两个Action:LoginAction和InsertAction。当然该Test中对应的DataTable应该有三个:Global、LoginAction和InsertAction;

    下面就详细的说一下DataTable是如何操作这些数据的:

    正文

    DataTable.Import "D:\data.xls"  '将data.xls中第一个叫Login表单内容导入到Test的Global表单中,将InsertOrder表单的内容导入到Test的LoginAction表单中,依次类推;感觉怪怪的,所以这个方法比较适合只导入Excel中第一个表单的内容

    DataTable.ImportSheet "D:\data.xls","Login","LoginAction" '将data.xls文件中的Login表单内容导入到当前Test的LoginAction表单中

    DataTable.GetSheet("Global").SetNextRow '设置下一行,红色表示要操作的表单名字
    columnCount = DataTable.GetSheet("Global").GetParametercount '取得Global表单中的总列数
    DataTable.GetSheet("Global").DeleteParameter ("列名") '运行时向Global表单中删除列

    DataTable.GetSheet("Global").SetPrevRow '设置上一行
    cellValue = DataTable.GetSheet("Global").GetParameter("列名") '取得Global表单中某列的值,可以这样写:DataTable.Value("列名","表单名字"),我喜欢这种写法

    rowCount = DataTable.GetSheet("Global").GetRowCount '取得Global表单中的总行数
    DataTable.GetSheet("Global").SetCurrentRow(3) '设置当前行为第3行
    DataTable.Value ("列名", "表单名字")="twf" '运行时设置某列值,例如DataTable.Value ("username", "LoginAction")="twf"

    DataTable.Export "D:\result.xls" '将当前Test的所有表单(LoginAction和InsertOrderAction、Global)中的所有内容全部导出到result.xls中

    DataTable.ExportSheet "D:\result.xls","LoginAction" '将当前Test的LoginAction表单中的内容导出到D:\result.xls文件中

    有问题多多指教,共同进步!您的关注会使俺快乐!!!

  • QTP访问数据库(推荐)

    2009-03-01 19:00:00

       这篇文章已经写好很久了,一直没更新到上面了,献丑了!!上次写了个只言片语,有点不负责任的感觉,这次就写个完整的吧!!Let's go!!

    一 、先给一个访问数据库的vbs脚本:

    使用的时候只需要调用下面标记为红色的三个函数基本就可以了

    '@Description 获取检索到数据集
    '@Documentation <selectCommandText>查询语句
    Public Function  FillDataTable(ByRef selectCommandText)
     Dim conn

     Set conn = getOleDbConnection()

     Dim cmd

     Set cmd = getOleDbCommandInstance()
     
     cmd.CommandText = selectCommandText
     cmd.Connection = conn
     Dim adapter
     Set adapter = getOleDbDataAdapterInstance()
     
     adapter.SelectCommand = cmd
     Dim data
     Set data = getDataTableInstance()

     adapter.Fill(data)

     conn.Close

     Set FillDataTable = data
    End Function

    '@Description 执行一条无返回结果集的Sql语句
    '例如Update 、Insert、delete语句
    '@Documentation <selectCommandText>查询语句
    Public Function  ExecuteNoQuery(ByRef selectCommandText)

     Dim conn

     Set conn = getOleDbConnection()

     Dim cmd

     Set cmd = getOleDbCommandInstance()
     
     cmd.CommandText = selectCommandText
     cmd.Connection = conn
     '返回影响的行数
     Dim resultCount
     resultCount =cmd.ExecuteNonQuery()

     conn.Close
     Set ExecuteNoQuery = resultCount
     
    End Function

    '@Description 执行查询,并返回查询所返回的结果集中第一行的第一列。忽略额外的列或行
    '例如Select count(*) from student
    '@Documentation <selectCommandText>查询语句
    Public Function  ExecuteScalar(ByRef selectCommandText)

     Dim conn

     Set conn = getOleDbConnection()

     Dim cmd

     Set cmd = getOleDbCommandInstance()
     
     cmd.CommandText = selectCommandText
     cmd.Connection = conn
     Dim resualtObject
     resualtObject = cmd.ExecuteScalar()

     conn.Close
     ExecuteScalar = resualtObject
     
    End Function

    '@Description获取OleDbConnection对象
    Private Function  getOleDbConnection()

     Set conn = DotNetFactory.CreateInstance("System.Data.OleDb.OleDbConnection")
      conn.ConnectionString =Environment.Value("ConnectionString") '我的数据库连接字符串在环境变量里面保存,原型如下:
      'Provider=SQLOLEDB;server=127.0.0.1;database=Northwind;uid=sa;pwd=sa
      conn.Open()

     Set getOleDbConnection = conn
    End Function

    '------------------------------------------------------------------------------------------------------------

    '@Description获取OleDbCommand的对象实例
    Private Function  getOleDbCommandInstance()
     Dim cmd

     Set cmd = DotNetFactory.CreateInstance("System.Data.OleDb.OleDbCommand")
     Set getOleDbCommandInstance = cmd
    End Function

    '@Description获取OleDbDataAdapter的对象实例
    Private Function  getOleDbDataAdapterInstance()

     Dim adapter
     Set adapter = DotNetFactory.CreateInstance("System.Data.OleDb.OleDbDataAdapter")
     Set getOleDbDataAdapterInstance = adapter
     
    End Function

    '@Description获取DataTable的对象实例
    Private Function  getDataTableInstance()
     Dim data
     Set data = DotNetFactory.CreateInstance("System.Data.DataTable")
     Set getDataTableInstance = data
    End Function

    '@Description获取DataSet的对象实例
    Private Function  getDataSetInstance()
     Dim data
     Set data = DotNetFactory.CreateInstance("System.Data.DataSet")
     Set getDataTableInstance = data
    End Function

    我写的这个访问数据库的底层代码主要是用于访问SQLServer数据库和Access数据库,很容易扩展写成专门访问SQLServer数据库或者Oracle数据库的代码,如果搞不明白,可以直接发邮件给我!

    二 、再给一个如何调用上述代码的实例:

    以SQLServer自带的NorthWind数据库为例,直接在QTP的专家视图里面写的代码,如下:

    Dim rowcount

    '获取Products表的记录数,这个返回值不是一个对象,所以不能这样写:Set rowcount = ExecuteScalar("Select Count(*) From Products")
    rowcount = ExecuteScalar("Select Count(*) From Products")
    msgbox rowcount

    Dim dtdata
    '获取Products中的所有数据,放到dtdata对象中
    Set dtdata = FillDataTable("Select * from Products")

    rowcount = dtdata.Rows.Count
    Dim i
    For i = 0 to rowcount -1

    'dtdata.Rows.get_Item(i)("ProductName")   获取第i行字段名称为ProductName的内容,
    '也可以这样写dtdata.Rows.get_Item(i)(1) 即可以是字段名也可以字段编号

    Reporter.ReportEvent micPass,"第"&i&"条记录","ProductName:"&dtdata.Rows.get_Item(Cint(i))("ProductName")&",QuantityPerUnit:"&dtdata.Rows.get_Item(Cint(i))("QuantityPerUnit")
    Next

     

    下面一个截图是通过QTP提供的Add Watch的功能学习如何使用DataTable中更多的属性和方法!很有用的哦!!

    如果发现有什么问题,欢迎指正,共同进步!!!

  • QTP通过.NET组件访问多种数据库的方法

    2008-09-25 17:43:13

       在编辑QTP脚本中经常需要访问数据库或者Excel,针对数据库或者文件的访问,大家最常用的应该是使用ADO的一系列对象,例如获取数据库连接对象:Set connObj = CreateObject("ADODB.Connection");获取记录集获取对象:Set rdsObj = CreateObject("ADODB.Recordset"),获取Excel文件访问对象:Set excelObj = CreateObject("Excel.Application")等等。不知道大家使用过程中有何感受,我感觉最不爽的地方就是读取记录集中的数据,必须要和数据库保持连接状态,并且还要使用循环来读取数据,不能一下子定位到我想要的数据(可能是自己还不太会用吧,抱歉O(∩_∩)O哈哈~)。曾经用C#写过几年的程序,感觉使用ADO.NET的系列对象来访问数据库、操作数据是相当的方便,所以一想到访问数据库和XML格式的数据就想到ADO.NET的数据库访问对象,DataSet、DataTable对数据的访问还是比较方便。最令人兴奋的是QTP可以通过创建数据库访问对象的方式使用ADO.NET,并且操作的方式和流程与在C#下编程思路没有多大区别。废话少说,言归正传。

    首先教给大家一个小知识,如何获取各种数据库连接字符串:

    新建一个文本文件,把它的扩展名修改成udl,名字可以任意起,如:db.udl,双击该文件按照操作提示即可获取,赶快试一下吧,很不错的。

    OK,开始我们的旅行吧!

     

      首先先附上一个通过.NET从SqlServer数据库读取数据的C#源代码(如果需要访问Access数据库,可以将访问对象修改成System.Data.OleDb下的相关对象,如果需要访问foxpro数据库,可以将访问对象修改成System.Data.Odbc下的相关对象,并且是通用的,Odbc基本可以访问大部分关系型数据库)

     public System.Data.DataTable GetAccessData(string selectCmdText)
     {

          string str = "server=.;database=StudentDB;uid=sa;pwd=sa";
          System.Data.SqlClient.SqlConnection conn = new SqlConnection();
          conn.ConnectionString = str;
          conn.Open();
          System.Data.SqlClient.SqlCommand cmd =new System.Data.SqlClient.SqlCommand();
          cmd.CommandText = selectCmdText;
          cmd.Connection = conn;
          System.Data.SqlClient.SqlDataAdapter adapter=new System.Data.SqlClient.SqlDataAdapter();
          adapter.SelectCommand = cmd;
          System.Data.DataTable dtdata = new DataTable();
          adapter.Fill(dtdata);
          conn.Close();
          return dtdata;
      }

    以上代码对应到QTP的vb脚本中如下所示:

    Dim conn
    Set conn = DotNetFactory.CreateInstance("System.Data.SqlClient.SqlConnection")
    conn.ConnectionString = "server=.;database=StudentDB;uid=sa;pwd=sa"
    conn.Open()

    Dim cmd

    Set cmd = DotNetFactory.CreateInstance("System.Data.SqlClient.SqlCommand")

    cmd.CommandText="select * from student"
    cmd.Connection = conn
    Dim adapter
    Set adapter = DotNetFactory.CreateInstance("System.Data.SqlClient.SqlDataAdapter")

    adapter.SelectCommand = cmd
    Dim dtdata

    Set dtdata= DotNetFactory.CreateInstance("System.Data.DataTable")
    dtdata.TableName="qtptest"
    adapter.Fill(dtdata)
    conn.Close

    msgbox dtdata.Rows.Count  '显示获取的数据条数

    今天事情真多,先写到这里吧,下次把通过DataSet对象对xml数据的操作给大家贡献出来,相信你会放弃使用通过ADO的对象访问xml数据的,只是个人见解,多提宝贵意见!!

Open Toolbar