65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 XML 轻松合并任何 Office 产品中的数据库字段

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.33/5 (4投票s)

2007年10月2日

CPOL

3分钟阅读

viewsIcon

17507

利用这段简单、优雅且强大的代码,您可以通过利用 XML 技术和基本的字符串操作,为用户提供高效的 Office 文档合并功能。

引言

这段代码使高级用户能够利用 Office(Microsoft 或任何其他兼容 XML 的 Office)的能力,让他们创建任意复杂(取决于他们的技能水平)的 Excel 或 Word 文档;只需使用基本的字段标记命名法。然后,通过在您的应用程序内(甚至可以使用 xp_cmdshell 从 SQL 中)运行此实用程序,即可为他们提供填充了实际数据的相同复杂文档。

背景

作为我工作公司中的开发经理,我需要为熟悉 Office 产品的高级用户提供解决方案。我一直在寻找一个好的工具或实用程序,能够让我简单地创建可以预先填充我们企业数据库中实际数据的 Office 文档;这样,用户就可以负责所有的外观和 Office 提供的工具,而无需手动输入我们基本系统中的数据。

网上很少有这样的示例,但大多数示例都需要比我愿意处理的更多的编程,或者需要外部组件(例如 Microsoft Interop DLL,它不是“自然”安装的;或者服务器需要它;而使用此代码,服务器甚至不需要安装 Office!)。我的一个原则是:“用最少的资源做最多的事,但编程要高效”。因此,我对 XML 和字符串操作做了一些研究,我认为这里提供的代码非常容易编程(甚至可以集成到您的任何 .NET 应用程序中,或使用任何其他语言从外部执行);而且功能强大。一个使用近 200KB XML 代码的非常复杂的 Excel 模板的测试,仅用了不到 2 秒就成功合并了。

Using the Code

关键是提供四个参数

  • 源 XML 模板的名称(例如,先前由“高级用户”在常规 Excel、Word 或他们喜欢的任何工具中创建并另存为标准 XML 的文件)。
  • 目标文件的名称(也必须是 XML 格式;并且预期由兼容 XML 的 Office 打开——MS Office 2003 和 2007 对用户来说是“透明的”,他们甚至不知道它是 XML)。
  • 模板中标记的预期字段列表(用户只需在标记之间输入字段名称,例如 [[Customer_Name]] )。例如:
    • CustName|CustLastName|Address|City|ZipCode
  • 实际值列表(可以从数据库或其他任何方式获得,然后作为输入参数传递给这个小程序)。例如:
    • John|Doe|123 Main Street|New York|08540

代码就像一个单一类一样简单,它以“行模式”打开 XML 文件并扫描所有行,每当找到标记的开始(在本例中是“[[”)时,它会尝试查找引用的字段并将其替换为写入输出文件。否则,它只会将原始输入字符串放入输出文件。

using System;
using System.IO;
using System.Text;
namespace XML_Merge
{
   class XML_Merge
   {
      public static int Main(string[] args) {
         StreamReader sr = new StreamReader(args[0]);
         string XmlLine="";
         string[] Fields=null;
         string[] Values=null;
         StreamWriter sw=new StreamWriter(args[1]);
         int i=0;
         if ( args.Length != 4  ) {
            Console.WriteLine("Parameters: ");
            Console.WriteLine("    Office_XML_Merge Source.XML " + 
              "Target.XML 'field1|field2|...|fieldn' 'value1|value2|...|valueN'");
            return(-1); // exit code
         }
         else {
            Fields=args[2].Split('|');
            Values=args[3].Split('|');
            if (Fields.Length != Values.Length) {
                Console.WriteLine("Warning!");
                Console.WriteLine("   Your fields string has " + 
                  "different number of items than your values string");
                return(-1);  // exit code
            }
            else
            {
               while( sr.Peek() >= 0 )
               {
                  XmlLine = sr.ReadLine();
                  i =XmlLine.IndexOf( "[[", 0 );
            
                  if (i>=0) {
                     for( i=0; i<Fields.Length; i++ ) 
                     XmlLine = XmlLine.Replace( "[["+Fields[i]+"]]", Values[i] );
                  }
             
                  sw.WriteLine(XmlLine);
               }
                    
               sr.Close();
               sw.Close();
               return(0); //Success
            }
         }         
      }
   }
}

关注点

老实说,这段代码不是什么高深的科学。然而,它足够快,能够完成它应该做的事情,并且不需要太多复杂的编程(无论是外部的还是第三方组件,除了 .NET Framework——你甚至不需要任何 Visual Studio!),却能获得巨大的好处,几乎可以在任何(不太老的)操作系统、任何编程语言中重用,甚至可以放在一个.BAT文件中。

我特别在 SQL 存储过程中使用它(请记住一个数据库原则:使数据库尽可能独立于应用程序)。我的应用程序中有一个简单的按钮,它调用一个存储过程。该存储过程只是为这个小应用程序创建输入字符串……Voilà!

下面是一个如何使用这个小程序(我省略了存储过程的所有细节,只留下了一个简单的 SQL 代码来说明用法)的示例。

declare @cmd nVarChar(4000)

set @cmd =
  Replace(
'C:\AppDir\Office_Xml_Merge.exe
 C:\AppDir\My_Template.XML
 C:\AppDir\Merged_001.XML
 "Today|Rec_Country|Rec_LC|Rec_LC_ID|Iss_Country|Iss_LC|
  Iss_LC_ID|Company|Iss_Comp|Address1|Address2|Iss_Address1|Iss_Address2" 
 "Oct 1, 2007|Mexico|Polanco|052005|United States|RockCenter|
  001211|Berlitz Inc.|Berlitz Mexico, S.A. de C.V.|
  400 Alexander Park|Princeton|Jaime Balmes 22A|Polanco"',
 char(13)+char(10), '' )

exec xp_cmdshell @cmd

历史

  • 初版,2007 年 10 月。
© . All rights reserved.