Разработка своего коннектора 1С для QlikView на C#

На сайте QlikCommunity можно найти материалы по SDK (v.11, v.10) для разработки своего коннектора. Нужные файлы находятся в разделе QVX SDK Libraries and Examples (QvxSDK_2.0.zip). В архиве находятся примеры, необходимые файлы для разработки, и документация. Для разработки нам потребуется Visual Studio. Знание C# необязательно, документации, примеров и умения пользоваться поиском оказалось вполне достаточно для создания примитивного коннектора.
Принцип работы коннектора

Создаем в Visual Studoi новый проект, копируем файлы QvxLibrary.dll и verpatch.exe из архива SDK в каталог проекта.

Добавляем ссылки на необходимые библиотеки в обозревателе решения.

На вкладке COM подключаем коннектор 1С.

На вкладке Обзор подключаем библиотеку QlikView

Выделяем проект C# (пункт connector1c), нажимаем Свойства (Alt+Enter).

Открываем вкладку «События построения», определяем событие после построения, в моем случае это «$(ProjectDir)verpatch.exe» «$(TargetPath)» /s «QlikView Connector» «start1c.blogspot.com»
Это нужно для того, чтобы после компиляции проекта запустился verpatch.exe и пропатчил созданный файл, иначе QlikView его не увидит. Наличие строки «QlikView Connector» обязательно, вторую строку определяете по своему усмотрению.

Создаем первый класс Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace connector1c
{

static class Program
{
///

/// Главная точка входа для приложения.
///

[STAThread]
static void Main(string[] args)
{
if (args != null && args.Length >= 2)
{
new Connector().Run(args[0], args[1]);
}
}
}
}

Класс Connector.cs отвечает за создание строки подключения для скрипта загрузки.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using QlikView.Qvx.QvxLibrary;
using System.Windows.Interop;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace connector1c
{
internal class Connector : QvxServer
{

QvConnector qv_connector;

public override QvxConnection CreateConnection()
{
qv_connector = new QvConnector();
return qv_connector;
}

public override string CreateConnectionString()
{
var base_connector = CreateBaseConnector((qv_connector == null) ? null:qv_connector.MParameters);
base_connector.ShowDialog();
string connectionString = null;
if (base_connector.DialogResult.Equals(true))
{
if (base_connector.GetServerBase())
{
connectionString = String.Format(«Srvr={0};Ref={1};UserId={2};Password={3};Query={4};QV_Table={5}»,
base_connector.GetBaseLocation(),
base_connector.GetBaseName(),
base_connector.GetUser(),
base_connector.GetPassword(),
base_connector.GetQueryText(),
base_connector.getQV_Table());
}
else
{
connectionString = String.Format(«File={0};UserId={1};Password={2};Query={3};QV_Table={4}»,
base_connector.GetBaseLocation(),
base_connector.GetUser(),
base_connector.GetPassword(),
base_connector.GetQueryText(),
base_connector.getQV_Table());
}

}
return connectionString;
}

private BaseConnector CreateBaseConnector(Dictionary mParams = null)
{
var base_connector = new BaseConnector(mParams);
var wih = new WindowInteropHelper(base_connector);
wih.Owner = MParentWindow;
return base_connector;
}

}
}

Класс QvConnector.cs реализует подключение к 1С по COM соединению, передачу текста запроса и считывание результата.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Security.Authentication;
using System.Text.RegularExpressions;
using QlikView.Qvx.QvxLibrary;
using System.Runtime.InteropServices;
using System.Reflection;
using System.IO;

namespace connector1c
{
[ComVisible(true)]
class QvConnector : QvxConnection
{

string connString;
V82.COMConnector v8connector;
string Srvr, File, Ref, Usr, Pwd, Query, QV_TableName;

public override void Init()
{

MParameters.TryGetValue(«File», out File);
MParameters.TryGetValue(«Srvr», out Srvr);
MParameters.TryGetValue(«Ref», out Ref);
MParameters.TryGetValue(«UserId», out Usr);
MParameters.TryGetValue(«Password», out Pwd);
MParameters.TryGetValue(«Query», out Query);
MParameters.TryGetValue(«QV_Table», out QV_TableName);

if (Srvr == null)
{
connString = «File='» + File + «‘;Usr='» + Usr + «‘;Pwd='» + Pwd + «‘;»;
}
else
{
connString = «Srvr='» + Srvr + «‘;Ref='» + Ref + «‘;Usr='» + Usr + «‘;Pwd='» + Pwd + «‘;»;
}

dynamic v8com = GetV8Connect();
if (v8com == null) return;

dynamic v8qBuilder = v8com.NewObject(«QueryBuilder»);
v8qBuilder.Text = Query;
var v8Fileds = new QvxField[v8qBuilder.Result.Columns.Count];
int i = 0;
foreach (var v8Column in v8qBuilder.Result.Columns)
{
v8Fileds.SetValue(new QvxField(v8Column.name, QvxFieldType.QVX_TEXT, QvxNullRepresentation.QVX_NULL_FLAG_SUPPRESS_DATA, FieldAttrType.ASCII), i++);
}

MTables = new List {
new QvxTable {
TableName = QV_TableName,
GetRows = GetData,
Fields = v8Fileds
}
};

Marshal.ReleaseComObject(v8qBuilder);
Marshal.ReleaseComObject(v8com);
Marshal.ReleaseComObject(v8connector);

}

private dynamic GetV8Connect()
{
v8connector = new V82.COMConnector();
return (v8connector == null) ? null : v8connector.Connect(connString);
}

private IEnumerable GetData()
{
QvxTable table = FindTable(QV_TableName, MTables);

if (table == null) yield return null;

dynamic v8com = GetV8Connect();
if (v8com == null)
{
yield return new QvxDataRow();
}

dynamic v8Query = v8com.NewObject(«Query»);
v8Query.Текст = Query;
dynamic result = v8Query.Execute;
dynamic m = result.Choose;
dynamic rezColumns = result.Columns;
var columnIdx = new Dictionary();
foreach (var mx in rezColumns)
{
columnIdx.Add(mx.name, rezColumns.IndexOf(mx));
}

QvxDataRow row;
while (m.Next() == true)
{
row = new QvxDataRow();
foreach(var tField in table.Fields)
{
int idx;
if (columnIdx.TryGetValue(tField.FieldName, out idx))
{
row[tField] = v8com.String(m.Get(idx));
};
}
yield return row;
}

Marshal.ReleaseComObject(v8Query);
Marshal.ReleaseComObject(result);
Marshal.ReleaseComObject(m);
Marshal.ReleaseComObject(v8com);
Marshal.ReleaseComObject(v8connector);

}

public override QvxDataTable ExtractQuery(string query, List qvxTables)
{
return base.ExtractQuery(query, qvxTables);
}

}
}

Для реализации ввода параметров подключения создана форма BaseConnector.xaml.








Логика взаимодействия с формой описана в классе BaseConnector.xaml.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Controls;
using System.Net.NetworkInformation;
using System.Diagnostics;

namespace connector1c
{
///

/// Логика взаимодействия для BaseConnect.xaml
///

public partial class BaseConnector : Window
{
public BaseConnector(Dictionary mParams = null)
{
InitializeComponent();

if (mParams != null)
{
string Srvr, File, Ref, Usr, Pwd, Query, QV_TableName;
mParams.TryGetValue(«File», out File);
mParams.TryGetValue(«Srvr», out Srvr);
mParams.TryGetValue(«Ref», out Ref);
mParams.TryGetValue(«UserId», out Usr);
mParams.TryGetValue(«Password», out Pwd);
mParams.TryGetValue(«Query», out Query);
mParams.TryGetValue(«QV_Table», out QV_TableName);

if (Srvr == null)
{
ServerBase.IsChecked = false;
base_location.Text = File;
}
else
{
ServerBase.IsChecked = true;
base_location.Text = Srvr;
base_name.Text = Ref;
}
username.Text = Usr;
password.Password = Pwd;
query_text.Text = Query;
qv_table.Text = QV_TableName;
}
setVisibility();

}

private void setVisibility()
{
Visibility elemVisibility = (ServerBase.IsChecked.Value) ? Visibility.Visible : Visibility.Hidden;
label_name.Visibility = elemVisibility;
base_name.Visibility = elemVisibility;
label_location.Content = (ServerBase.IsChecked.Value) ? «Сервер» : «Каталог»;
}

private void btnCancel_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
Close();
}

private void btnOk_Click(object sender, RoutedEventArgs e)
{
DialogResult = true;
Close();
}

private void ServerBase_Click_1(object sender, RoutedEventArgs e)
{
setVisibility();
}

public bool GetServerBase()
{
return ServerBase.IsChecked.Value;
}

public string GetBaseLocation()
{
return base_location.Text;
}

public string GetBaseName()
{
return base_name.Text;
}

public string getQV_Table()
{
return qv_table.Text;
}

public string GetQueryText()
{
return query_text.Text;
}

public string GetUser()
{
return username.Text;
}

public string GetPassword()
{
return password.Password;
}

private void Hyperlink_Start1c(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
{
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
e.Handled = true;
}

}
}

После компиляции проекта полученный файл и библиотеку QvxLibrary.dll необходимо скопировать в %PROGRAMFILES%\Common Files\QlikTech\Custom Data\, в моем случае это C:\Program Files (x86)\Common Files\QlikTech\Custom Data\connector1c. Отсутствующие каталоги необходимо создать вручную. После этого запускаем QlikView, коннектор доступен в списке вариантов подключения.

Исходники проекта C#, connector1c.zip. Успехов в создании своих коннекторов.

Найти решение у бизнес-партнера QlikTech (QlikView) в России.

Форум разработчиков QlikView и Qlik Sense. Получите ответы на все вопросы по QlikView и Qlik Sense!

Вы можете оставить комментарий, или ссылку на Ваш сайт.

Оставить комментарий

64 queries in 0,200 seconds