DbToDocx Windows Workflow Activity
Статья описывает Windows Workflow Activity DbToDocx. Activity разработан на языке C#. Activity читает содержимого полей одной или нескольких таблиц базы данных, формирует на основе считанных данных DataSet, затем из DataSet формирует Word docx документ и в нем таблицу с данными , далее записывает документ на диск в виде файла Docx, передает данные клиенту посредством Web Service технологии WCF.
Представлен рабочий проект MS Visual Studio 2010 WCF + WorkFlow, в котором применяется описываемое Activity. В состав проекта входят WorkFlow, библиотека входных и выходных классов, Windows Form клиент запрашивающий, получающий и отображающий данные с сервера при помощи компонента DataGridView и Microsofr Word.
1. Входные данные Activity DbToDocx.
Входные аргументы для Activity собраны в классе InputArguments и состоят из трех полей:
code
public class InputArguments
{
public string ConnectStrig { get; set; }
public string SqlCommand { get; set; }
public string nameFile { get; set; }
}
2. Выходные данные Activity DbToDocx.
Выходные аргументы для Activity находяться в класса OutputResult и состоят из трех свойств: byteDocx - выходной документ формата Docx, dataSet и Error - сообщения о потенциально возможной ошибке. Примечание. Клиенту достаточно передавать два объекта:dataSet и Error, передача byteDocx - избыточна.
code
public class OutputResult
{
public string Error { get; set; }
public DataSet dataSet { get; set; }
public byte[] byteDocx { get; set; }
}
3. Исходный текст Activity DbToDocx.
Класс реализующий Activity DbToDocx создан асинхронным, содержащим два метода:
- BeginExecute;
- EndExecute.
Как видно из приведенного ниже текста, SQL запрос запускается в методе BeginExecute, затем работа Activity приостаналивается и завершается процесс в методе EndExecute.
code
/* 27.09.2012. Activity DbToDocx. Рекомендуется для публикации
1. Activity читает содержимое таблицы в базе данных Northwind и переводит их в DataSet,
затем, создает документ Word *.docx, преобразовывает DataSet в таблицу Docx,
записывает созданный Word документ диск в виде файла Docx.
2. Входным параметром является класс InputArguments с полями:
public string ConnectStrig { get; set; }
public string SqlCommand { get; set; }
public string nameFile { get; set; }
3. Выходным аргументом является класс OutputResult с полями:
public string Error { get; set; }
public DataSet dataSet { get; set; }
public byte[] byteDocx { get; set; }
4. Клиент передает InputArguments, принимает OutputResult. Отображает DataSet
в DataGridView, из byte[] byteDocx формирует Word документ, записывает его
на диск и отображает.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Activities;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Windows.Markup;
using System.ComponentModel;
using System.Reflection;
using Word = Microsoft.Office.Interop.Word;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using ClassLibrary;
namespace ActivityLibrary
{
public sealed class DbToDocx : AsyncCodeActivity<OutputResult>
{
// Input Object
[RequiredArgument]
[DefaultValue(null)]
public InArgument<InputArguments> inputArguments { get; set; }
// Temporary variable for Input Arguments
private InputArguments inputObject = null;
private string connectStr = null;
private string cmdSQL = null;
private string nameFile = null;
private string activityDirectory = null;
//Output Object
private OutputResult OutRes = null;
// Temporary use variable
private DataSet dataSet = null;
private SqlConnection connect = null;
private SqlCommand command = null;
private SqlDataAdapter adapter = null;
private SqlDataReader reader = null;
private Word._Application word = null;
private Word._Document document = null;
Object missing = (Object)Type.Missing;
protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
{
try
{
// Input Object
inputObject = inputArguments.Get(context);
// Connection string
connectStr = inputObject.ConnectStrig;
// Command string
cmdSQL = inputObject.SqlCommand;
// Name File for write docx
nameFile = inputObject.nameFile;
// If connect string is empty
if (String.IsNullOrEmpty(connectStr)) throw new ArgumentNullException("Value", "Connection String is Empty");
// If command string is empty
if (String.IsNullOrEmpty(cmdSQL)) throw new ArgumentNullException("Value", "Command String is Empty");
// If nameFile string is empty
if (String.IsNullOrEmpty(nameFile)) throw new ArgumentNullException("Value", "File Name String is Empty");
connect = new SqlConnection(connectStr);
connect.Open();
command = new SqlCommand(cmdSQL, connect);
adapter = new SqlDataAdapter(command);
context.UserState = adapter;
return adapter.SelectCommand.BeginExecuteReader(callback, state);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return null;
}
}
protected override OutputResult EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
{
try
{
SqlDataAdapter adapter = (SqlDataAdapter)context.UserState;
//Create Output Object
OutRes = new OutputResult();
// End Execute Reader
reader = adapter.SelectCommand.EndExecuteReader(result);
reader.Close();
// Create DataSet
dataSet = new DataSet();
adapter.Fill(dataSet);
// Count Rows and Columns
int countRows = dataSet.Tables[0].Rows.Count;
int countField = dataSet.Tables[0].Columns.Count;
// countRows = 105; //debugging
// Create Word document
word = new Word.Application();
word.Visible = false;
document = word.Documents.Add();
word.Selection.TypeText("SQL: " + cmdSQL);
document.Tables.Add(word.Selection.Range, countRows, countField,
Word.WdDefaultTableBehavior.wdWord9TableBehavior,
Word.WdAutoFitBehavior.wdAutoFitContent);
for (int itemRow = 1; itemRow <= countRows; itemRow++)
{
for (int itemColumn = 1; itemColumn <= countField; itemColumn++)
{
word.ActiveDocument.Tables[1].Cell(itemRow, itemColumn).Range.InsertAfter(dataSet.Tables[0].Rows[itemRow - 1].ItemArray[itemColumn - 1].ToString());
}
}
// Output text in end Page
word.Selection.GoTo(Word.WdGoToItem.wdGoToLine, Word.WdGoToDirection.wdGoToLast, ref missing, ref missing);
word.Selection.TypeParagraph();
word.Selection.TypeText("All in Table: " + countRows.ToString() + " rows");
// Write File in directory Activity
activityDirectory = AppDomain.CurrentDomain.BaseDirectory;
document.SaveAs(activityDirectory + nameFile);
// Close All
document.Close(ref missing, ref missing, ref missing);
word.Quit(ref missing, ref missing, ref missing);
document = null;
word = null;
// Read File in byte[]
OutRes.byteDocx = File.ReadAllBytes(activityDirectory + nameFile);
OutRes.dataSet = this.dataSet;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
this.OutRes.Error = ex.ToString();
}
finally
{
if (document != null)
{
document.Close(ref missing, ref missing, ref missing);
document = null;
}
if (word != null)
{
word.Quit(ref missing, ref missing, ref missing);
word = null;
}
GC.Collect();
GC.WaitForPendingFinalizers();
this.connect.Close();
}
return OutRes;
}
}
}
4. Клиент для Activity DbToDocx
Ниже приведен пример
клиента, который организует запрос к серверу, принимает и отображает данные в DataGridView и в Microsofr Word.
code
>
/* 27.09.2012
Клиент для проверки Activity DbToDataSet.
1. Формирует и передает на сервер объест InputArguments.
2. Принимает и отображает объест OutputResult содержащий DataSet и Docx документ
в виде byte[].
3. Записывает на диск файл tempory.docx
4. Считывает с диска и отображает tempory.docx
5. Отображение приянятые данные в DataGridView.
Примечание: Преобразование DataSet в docx можно выполнять и на клиенте.
*/
using System;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Windows.Forms;
using ClassLibrary;
using System.Diagnostics;
using System.Reflection;
using Word = Microsoft.Office.Interop.Word;
using System.IO;
namespace WindowsFormsClient
{
public partial class Form1 : Form
{
private ServiceReference.ServiceClient client;
private ClassLibrary.InputArguments input;
private ClassLibrary.OutputResult output;
private Word._Application word = null;
private Word._Document document = null;
Object missing = (Object)Type.Missing;
public Form1()
{
InitializeComponent();
client = new ServiceReference.ServiceClient();
input = new InputArguments();
output = new OutputResult();
textBox2.Text = @"Data Source=PROGR\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True; Asynchronous Processing=true";
textBox3.Text = @"SELECT Orders.OrderID, Orders.CustomerID, Orders.ShipAddress FROM Orders";
textBox1.Text = "DbToDocx.docx";
}
private void button1_Click(object sender, EventArgs e)
{
try
{
// Input string for connect
input.ConnectStrig = textBox2.Text;
// Input SQL command
input.SqlCommand = textBox3.Text;
// Input name File for write
input.nameFile = textBox1.Text;
// Set null view
this.dataGridView1.DataSource = null;
this.dataGridView1.Update();
// Send and receive data
output = client.GetData(input);
// Write docx File in Disk
File.WriteAllBytes(@"g:\tempory.docx", output.byteDocx);
// Open docx File
word = new Word.Application();
document = word.Documents.Open(@"g:\tempory.docx");
word.Visible = true;
// View data
this.dataGridView1.DataSource = output.dataSet.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
Visual Studio 2010 проект содержащий: Activity, Workflow для Activity, Windows Form клиент можно загрузить.
Евгений Вересов.
27.09.2012 года.
|