
На видео можно посмотреть, что у меня получилось, работа с QlikView начинается c 04:35.
Принцип работы коннектора
Создаем в 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
{
/// <summary>
/// Главная точка входа для приложения.
/// </summary>
[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<string, string> 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<QvxTable> {
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<QvxDataRow> 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<string, int>();
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<QvxTable> qvxTables)
{
return base.ExtractQuery(query, qvxTables);
}
}
}
Для реализации ввода параметров подключения создана форма BaseConnector.xaml.
<Window x:Class="connector1c.BaseConnector"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Title="Параметры подключения" WindowStartupLocation="CenterOwner" Width="430" Height="438" ResizeMode="CanResize" ShowInTaskbar="False">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="373*"/>
<RowDefinition Height="35"/>
</Grid.RowDefinitions>
<CheckBox x:Name="ServerBase" Content="Клиент/Сервер" HorizontalAlignment="Left" Margin="122,9,0,0" VerticalAlignment="Top" Width="290" Click="ServerBase_Click_1" Height="16"/>
<TextBox x:Name="base_location" Height="23" Margin="122,30,10,0" TextWrapping="Wrap" VerticalAlignment="Top"/>
<TextBox x:Name="base_name" Height="23" Margin="122,58,10,0" TextWrapping="Wrap" VerticalAlignment="Top"/>
<Label x:Name="label_location" Content="Путь" HorizontalAlignment="Left" Margin="10,27,0,0" VerticalAlignment="Top" Width="87" Height="26"/>
<Label x:Name="label_name" Content="Имя базы" HorizontalAlignment="Left" Margin="10,56,0,0" VerticalAlignment="Top" Width="87" Height="26"/>
<Label x:Name="username_label" Content="Пользователь" HorizontalAlignment="Left" Margin="10,93,0,0" VerticalAlignment="Top" Width="87" Height="26"/>
<Label x:Name="password_label" Content="Пароль" HorizontalAlignment="Left" Margin="10,121,0,0" VerticalAlignment="Top" Width="87" Height="26"/>
<TextBox x:Name="username" Height="23" Margin="122,93,10,0" TextWrapping="Wrap" VerticalAlignment="Top" ToolTip="Login"/>
<PasswordBox x:Name="password" Height="23" Margin="122,121,10,0" VerticalAlignment="Top" ToolTip="Password"/>
<TextBox x:Name="query_text" KeyboardNavigation.AcceptsReturn="True" Margin="10,219,10,10" TextWrapping="Wrap" UndoLimit="93" ToolTip="Текст запроса"/>
<Button x:Name="btnOk" Content="Ok" HorizontalAlignment="Left" Margin="10,0,0,10" Width="75" Click="btnOk_Click" Grid.Row="1" />
<Button x:Name="btnCancel" Content="Cancel" HorizontalAlignment="Left" Margin="90,0,0,10" Width="75" Click="btnCancel_Click" Grid.Row="1"/>
<Label Content="Текст запроса" HorizontalAlignment="Left" Margin="10,188,0,0" VerticalAlignment="Top" Width="87" Height="26"/>
<Label x:Name="QV_table_label" Content="Таблица QV" HorizontalAlignment="Left" Margin="10,152,0,0" VerticalAlignment="Top" Width="87" Height="26"/>
<TextBox x:Name="qv_table" Height="23" Margin="122,155,10,0" TextWrapping="Wrap" VerticalAlignment="Top" ToolTip="Таблица QlikView"/>
<Label Margin="0,0,10,10" FontSize="9" Grid.Row="1" HorizontalAlignment="Right" Width="98" ToolTip="Welcome :)" >
<Hyperlink NavigateUri="http://start1c.blogspot.com" RequestNavigate="Hyperlink_Start1c" Block.TextAlignment="Right" >start1c.blogspot.com</Hyperlink>
</Label>
</Grid>
</Window>
Логика взаимодействия с формой описана в классе 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
{
/// <summary>
/// Логика взаимодействия для BaseConnect.xaml
/// </summary>
public partial class BaseConnector : Window
{
public BaseConnector(Dictionary<string, string> 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\<connector dir>, в моем случае это C:\Program Files (x86)\Common Files\QlikTech\Custom Data\connector1c. Отсутствующие каталоги необходимо создать вручную. После этого запускаем QlikView, коннектор доступен в списке вариантов подключения.
Исходники проекта C#, connector1c.zip. Успехов в создании своих коннекторов.
Update 09/12/2015
Коллега наткнулся на проблему при использовании verpatch из архива SDK. После сборки проекта при патче результата возникала ошибка:
Exception in ParseBinaryVersionResource
Error in ParseBinaryVersionResource
error parsing version info from the file
Some of actions failed, exiting
Для решения проблемы необходимо скачать обновленную версию verpatch. В документации SDK есть ссылка на ресурс http://www.codeproject.com/KB/install/VerPatch.aspx. Так же можно использовать альтернативный источник https://ddverpatch.codeplex.com.
Михаил, добрый день.
ОтветитьУдалитьПри попытке запустить ваш коннектор на Windows Server 2008 R2
(брал файлы из папки connector1c.zip\connector1c\connector1c\bin\Release)
Программа коннектор видит, но при попытке соединиться выдаёт ошибку:
"Выбранный соединитель прекратил работу или был отключен
connector1c.exe (32)(start1c.blogspot.com)"
Что можно сделать в данной ситуации?
Заранее, спасибо.
С уважением, Антон.
День добрый,
Удалитьдля начала нужно проверить, установлена ли платформа 1С на этом сервере. Коннектор использует библиотеку comcntr.dll для подключения.
День добрый Михаил,
ОтветитьУдалитьне подскажите с чем может быть связана данная ошибка:
QVX_UNKNOWN_ERROR: Не удалось получить фабрику класса COM для компонента с CLSID {2B0C1632-A199-4350-AA2D-2AEE3D2D573A} из-за следующей ошибки: 80040154 Класс не зарегистрирован (Исключение из HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))
Полагаю, разработка ведется на x64 системе. COM-connector 1С является 32-битным.
ОтветитьУдалитьПосмотрите
http://forum.infostart.ru/forum14/topic33442/
http://devtrainingforum.v8.1c.ru/forum/thread.jsp?id=558085&threadtype=0
http://miko.ru/blogs/SwordBlog/54/
http://biconsult.ru/sites/default/files/downloads/BIConsult_QlikView-1C-Connector_11.3_User_guide.pdf
Я на своей x64 машине регистрировал COM-connector в COM+ компонентах.
http://www.sql.ru/forum/802087/v81-comconnector-na-server-2008-r2-64
http://kb.mista.ru/article.php?id=870
Спасибо Михаил за ответ, вроде все сделал, но теперь появилась другая ошибка:
УдалитьSystem.NullReferenceException: Ссылка на объект не указывает на экземпляр объекта.
в System.Dynamic.ExcepInfo.GetException()
в System.Dynamic.ComRuntimeHelpers.CheckThrowException(Int32 hresult, ExcepInfo& excepInfo, UInt32 argErr, String message)
в CallSite.Target(Closure , CallSite , ComObject )
в System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
в CallSite.Target(Closure , CallSite , Object )
в System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
в connector1c.QvConnector.Init() в d:\!tmp\qw\connector1c\connector1c\QvConnector.cs:строка 46
в QlikView.Qvx.QvxLibrary.QvxConnection.Connect(String connectionString, QvxConnectOptions options, QvxServer qvxServer)
в QlikView.Qvx.QvxLibrary.QvxServer.HandleConnect(QvxRequest request)
в QlikView.Qvx.QvxLibrary.QvxServer.HandleRequest(QvxRequest request)
в QlikView.Qvx.QvxLibrary.QvxServer.Run(String parentString, String pipeName)
У меня Win7 x64, Qv32...
Где может еще быть мой бок?
Спасибо, очень полезная у Вас инфа!!!
Могу предположить, что это из-за перекомпиляции на основе моего проекта. На всякий случай стоит заново подключить библиотеку QvxLibrary к текущему проекту.
УдалитьДобрый день, Михаил.
УдалитьЯ зарегистрировал COM-connector в COM+ компонентах (по инструкции http://kb.mista.ru/article.php?id=870)
И назвал его connector1c
Загрузка по прежнему выдаёт ошибку: Не удалось получить фабрику класса COM для компонента с CLSID {2B0C1632-A199-4350-AA2D-2AEE3D2D573A} из-за следующей ошибки: 80040154 Класс не зарегистрирован (Исключение из HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).. Stack trace written to C:\ProgramData\QlikTech\Custom Data\connector1c\Log\StackTrace.txt
Что необходимо подправить в коде?
Могли бы вы выложить перекомпилированный коннектор, для подключения к 64 битному серверу?
День добрый, в архиве лежат две версии, для x86 и для x64.
УдалитьВ коде больше поправить нечего, на всякий случай проверьте активность ссылки на com connector 1С в свойствах проекта.
Добрый день, Михаил!
УдалитьВы можете выложить версию для 1С 8.3
Заранее благодарен!
Андрей, доброго времени суток.
УдалитьВыкладывать не буду, скачать и перекомпилировать вы сможете сами, информации достаточно.
Более того, советую вам не заморачиваться с коннекторами, работающими с 1С через COM-соединение.
Это самый медленный вариант реализации получения данных, не считая нагрузки на базу при больших объемах запрашиваемых данных. Вообще, любой коннектор, обращающийся к базе 1С можно считать нежелательным решением. На мой взгляд, лучше реализовать консолидацию необходимых данных во внешнюю СУБД, тот же самый SQL, и дергать данные из него.
Михаил, Добрый день!
ОтветитьУдалитьСкомпилировала коннектор для работы с 1С 8.3. Вроде всё корректно отрабатывает, в логи записи никакие не уходят, ошибок не выдает. Но окно с результатом загрузки в QlikView пустое. Данные не загружаются.
Подскажите пожалуйста, с чем это может быть связано?
День добрый. А доступные поля при создании новых объектов qlikview появляются?
УдалитьСпасибо большое, всё решились припиской вот такой вот части кода (SQL Select * From продажи;) после текста, сформированного коннектором. Данные загрузились как следует. Спасибо Вам за Ваше замечательное творение!
УдалитьВам спасибо, что воспользовались :) Понял, в чем ваша проблема была. Если посмотрите на видео, на время 5:38 - изначально текст генерируется без команды SQL SELECT ... После нажатия на кнопку "Выбрать" появляется конструктор выражения SELECT (5:50). После конструирования выражения финальная часть кода (SQL Select * FROM Продажи;) появляется скрипте загрузки. После этого можно выполнять скрипт.
УдалитьДоброго времени суток, Михаил.
ОтветитьУдалитьПодскажите пожалуйста, когда вы регистрировали COM-connector, какое Вы давали ей имя?
comconnector создал вот такая ошибка стала вываливаться, не могу разобраться в чём дело. помогите
ОтветитьУдалитьQVX_UNKNOWN_ERROR: В результате вызова компонента COM возвращена ошибка в формате HRESULT E_FAIL.. Stack trace written to C:\Documents and Settings\All Users\Application Data\QlikTech\Custom Data\connector1c\Log\StackTrace.txt
День добрый. Полагаю, у вас что-то с регистрацией com-connector'а 1С. Выше по ссылкам можно поискать решение. У меня такой проблемы не возникало, вряд ли что-то подскажу.
УдалитьДобрый день, воспользовался Вашим коннектором для загрузки данных из 1с. Данные загрузил, но могу только сформировать простую таблицу, диаграммы создать не получается. Что не так сделал?
ОтветитьУдалитьПривет. Если простая таблица формируется, то и диаграмма должна тоже без проблем создаваться. Можно попробовать построить на этих данных простую гистограмму, с одним измерением и выражением. Если не получиться, то тут только смотреть надо.
УдалитьУже пробовал, пишет нет данных для отображения. Выгружал данные из 1с в таблицу excel, потом в qlik подгружал все нормально формирует. Что смотреть не подскажите?
УдалитьДумаю, понял. Скорей всего проблема с типом поля, qlik не определяет его как числовое. Проверьте в вашей таблице (Ctrl+Alt+D, вкладка "Таблицы") какие теги у полей, которые должны считаться в диаграмме.
Удалитьstext
УдалитьВот и ответ, должен быть так же тэг numeric или integer. Смотрите тогда сам запрос, по нужному полю где то возвращается значение, которое qlik не может распознать как числовое. Либо кидайте текст запроса сюда.
Удалитьзапрос из 1с?
УдалитьВЫБРАТЬ
УдалитьПродажиОбороты.Номенклатура,
ПродажиОбороты.ДоговорКонтрагента,
ПродажиОбороты.Организация КАК Организация,
ПродажиОбороты.Контрагент,
СУММА(ПродажиОбороты.КоличествоОборот) КАК КоличествоОборот,
СУММА(ПродажиОбороты.СтоимостьОборот) КАК СтоимостьОборот
{ВЫБРАТЬ
Организация.*,
Контрагент.*,
ДоговорКонтрагента.*,
Номенклатура.*}
ИЗ
РегистрНакопления.Продажи.Обороты КАК ПродажиОбороты
ГДЕ
НЕ ПродажиОбороты.СтоимостьОборот = 0
СГРУППИРОВАТЬ ПО
ПродажиОбороты.Номенклатура,
ПродажиОбороты.ДоговорКонтрагента,
ПродажиОбороты.Организация,
ПродажиОбороты.Контрагент
УПОРЯДОЧИТЬ ПО
Организация
Да, можно в почту, ссылка вверху страницы.
Удалитьзапрос здесь оставил.
УдалитьЗапрос в порядке, я на таких же коннектор тестировал. Попробуйте, если есть возможность, ради эксперимента убрать из текста запроса конструкцию в фигурных скобках. Коннектор использует построитель запроса 1С для получения колонок, может где-то и врет с типами. Сам смогу попробовать только после праздников :)
УдалитьДобрый день, Михаил! а можно подобный коннектор создать для 1с 7.7? И в чем будут отличия?
ОтветитьУдалитьДень добрый, Дмитрий. Да, в общих чертах, можно. В классе QvConnector необходимо переписать с учетом языка 77 участок получения заголовков полей колонок запроса. Для v8 я получал с помощью построителя запроса:
Удалитьdynamic v8qBuilder = v8com.NewObject("QueryBuilder");
Так же необходимо переписать участок загрузки результата запроса, начинается с
dynamic v8Query = v8com.NewObject("Query");
Да, да, я нашел эти участки кода. Я буду использовать выгрузку результата запроса в ТаблицуЗначений и получать заголовки столбцов оттуда. Сложность в в том что работа с объектом V77.Application проходит с помощью функций InvokeMember, а это очень неудобно. Посоветуйте, что лучше: написать простенькую обертку для этого объекта или не мучиться с ней?
УдалитьПосмотрел примеры с 7.7, InvokeMember вроде бы и одной строкой, а большинство параметров неизменно. Я бы вынес в отдельную функцию, встреться мне такой участок в коде более двух раз :)
Удалитьда, так будет лучше всего, понятнее по крайней мере)) Спасибо за ваш ответ!
УдалитьДобрый день, Михаил! появилась одна проблема с коннектором к 1с7.7: если оставить методы освобождения ресурсов Marshal.ReleaseComObject(...);... в методе public override void Init() класса QvConnector, то появляется ошибка: типа "не могу найти СОМ объект". А если эти методы убрать, то в памяти остается висеть 1ска...
УдалитьНе могу понять куда мне разместить методы освобождения СОМ объектов
а, все сам разобрался)) Создал обертку для СОМ объекта и вызывал Marshal.ReleaseComObject(...) для нее, а не для самого объекта)))
Удалитьтеперь другая проблема: запрос к базе выполняется два раза - 1 - для получения заголовков, 2 - для получения строк. Что с этим делать не знаю, в 1сV7.7 кажется нет QueryBuilder
УдалитьДумаю, стоит добавить параметр в процедуру получения данных. Ориентируясь на значение параметра можно, например, при получении заголовков программно добавлять в запрос невыполнимое условие. Или же условие добавить в текст запроса по умолчанию, потом удалять по условию. Либо ввести в запрос переменную. Под рукой нет базы с реальными данными, чтобы проверить быстродействие, набросал для примера:
УдалитьЗапрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(Сформировать)
|ТекущийЭлемент = Справочник.Спр.ТекущийЭлемент;
|Код = Справочник.Спр.Код;
|Рек1 = Справочник.Спр.Рек1;
|Рек2 = Справочник.Спр.Рек2;
|Группировка ТекущийЭлемент;
|Условие(ВсеСтроки = 1);
|"//}}ЗАПРОС
;
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
Возврат;
КонецЕсли;
Т = СоздатьОбъект("ТаблицаЗначений");
Запрос.Выгрузить(Т, 1);
Этот комментарий был удален автором.
УдалитьСпасибо, проверю. Еще одна неожиданность от QlikView - при формировании строки подключения в скрипт заносится в том числе и текст запроса, так вот QlikView ругается на элементы запроса типа: "Слово" пробел "Слово", например:
УдалитьГруппировка ТекущийЭлемент.
Можно ли ему объяснить чтобы он "не умничал" и не контролировал эту строку?
Скиньте, что получается в строке подключения.
УдалитьCUSTOM CONNECT TO "Provider=connector1c.exe;File=C:\\1C\\DB\;Query=Наименование = Справочник.Номенклатура.Наименование;Код = Справочник.Номенклатура.Код;Группировка Наименование;Группировка Код;Без Итогов;;QV_Table=Таблица;XUserId=GDFGBIDSQGNBNeCaYFUbLIDXROADNBGaAEUBbILQQWPDNAKI;XPassword=MFJDaYD;";
УдалитьВроде нормальная строка. Можно еще текст ошибки самого QlikView? А ругается только на группировки? или на "Без итогов" тоже?
УдалитьПроверьте, что получится, если удалить эти строки:
Группировка Наименование;
Группировка Код;
Без Итогов;
QVX_UNKNOWN_ERROR: Parameter "Группировка Наименование" has no value, or misplaced semicolon
УдалитьКажется ему не нравились точки-с-запятой (;)
УдалитьCUSTOM CONNECT TO "Provider=connector1c.exe;File=C:\\1C\\MILEX\;Query=Наименование = Справочник.Номенклатура.Наименование
УдалитьКод = Справочник.Номенклатура.Код
Группировка Наименование
Группировка Код
Без Итогов;QV_Table=Номеклатура;XUserId=JDBKEILSQGMBddCaVFUbbILQQGOBdeGT;XPassword=AFWEAdD;";
Вот эта строка всех устроила))
Этот комментарий был удален автором.
Удалитьвсех кроме 1С (((
УдалитьПридется что-то в коде кодить чтоб запятые вставить в текст запроса...
CUSTOM CONNECT TO "..." по сути, является строкой с разделителями в виде ";". Описание каждой секции состоит из переменной, "=" и значения переменной. В запросе для v8 все просто, там символы ";" отсутствуют. Для запроса v7 у нас соответственно проблема.
Удалитьрешил их следующим образом:
Удалитьв сроке запроса вместо ";" ставлю "|",
Наименование = Справочник.Номенклатура.Наименование
|Код = Справочник.Номенклатура.Код
|Группировка Наименование
|Группировка Код
|Без Итогов|
в коде выполняю Replace('|', ';'), и месте получения заголовков полей к строке запроса добавляю Условие(0 = 1);
Все вроде работает и лишний раз запрос не выполняется.
Вот еще какой вопрос, можно ли в коннекторе реализовать полосу прогресса на время выполнения запроса?
Поздравляю :) По поводу индикатора выполнения - настолько глубоко не копал. Лучше обратиться к документации, ссылки в начала страницы.
Удалитьспасибо вам за ответы!!
УдалитьДобрый день, Михаил! Скажите существуют соответствующие библиотеки для разработки коннектора к Qlik Sense?
УдалитьЯ не интересовался. Для Sense существует отдельный раздел https://community.qlik.com/community/qlik-sense/resource-library, можете посмотреть там.
УдалитьСобственно :) https://help.qlik.com/sense/en-US/developer/
УдалитьАга, я нашел эту ссылку. Буду разбираться. На первый взгляд проблем быть не должно.
УдалитьУ меня еще один вопрос появился . важный, но, в принципе, не критичный: Если передать коннектору запрос с ошибкой, то 1С виснет, приходится снимать задачу, а потом индексировать базу... Можно ли как-то перехватить эту исключительную ситуацию и предотвратить зависание 1С?
В коннекторе вставляю вызов запроса в блок try-catch, но это не спасает, коннектор не ругается, а 1С все равно висит.
ExecuteBatch() выолняет последовательность операторов,но не возвращает значение, а EvalExpr() возвращает результат, но не выполняет последовательность операторов... заколдованный круг, блин...
Вряд ли подскажу. В качестве альтернативы могу предложить создать экспортную функцию в общем модуле, передавать в нее текст запроса, выполнять в обертке Попытка Исключение КонецПопытки, возвращать таблицу значений, либо 0 в случае ошибки.
УдалитьСпасибо вам!!
УдалитьДобрый день, Михаил! Продолжаю терроризировать вас вопросами)))
УдалитьВопрос в следующем: после передачи данных из 1с с помощью коннектора они распознаются QlikView как строковый тип, а не как дата или число(( Что можно с этим поделать?
Добрый. У меня за это это в процедуре IEnumerable, код:
Удалить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));
};
}
Как видите, я обращался к функции 1С для преобразования значения в строку.
Мне было этого достаточно, полученные строковые значения QlikView корректно распознавал в необходимые типы.
Вы можете добавить в этот участок дополнительные проверки на типы 1С и соответсвующие обработки значений.
...QlikView корректно распознавал в необходимые типы....
Удалитьт.е. числа видел как числа, а не как строки? Или вам и нужны были только строки?
Вот еще одна строка:
Удалитьv8Fileds.SetValue(new QvxField(v8Column.name, QvxFieldType.QVX_TEXT, QvxNullRepresentation.QVX_NULL_FLAG_SUPPRESS_DATA, FieldAttrType.ASCII), i++);
и параметр FieldAttrType.ASCII говорит о том как QlikView интерпретировать тип поля. Тут стоит строковый тип
... FieldAttrType.INTEGER - целое и т.д., сложность в том как определить тип значения поля в ТаблицеЗначений 1с
УдалитьЭтот комментарий был удален автором.
ОтветитьУдалитьДобрый день. В начале статьи ссылка битая. Можете перезалить архив
ОтветитьУдалитьhttp://community.qlikview.com/docs/DOC-2689
Удалитьна странице есть ссылка на SDK
А как сделать аналогично ля версии 8,3 и w10? попробовал пошагово выполнить все что указано, не получилось:(
ОтветитьУдалить