Независимый форум, посвященный системе БОСС-Кадровик и всему, что с ней связано
|
|
Предыдущая тема :: Следующая тема |
Автор |
Сообщение |
Константин
Зарегистрирован: 02.05.2012 Сообщения: 39 Откуда: Красноярск
|
Добавлено: Пт Май 04, 2012 10:15 Заголовок сообщения: Отчет в Excel с большим количеством строк и форматированием+ |
|
|
Сделали по заказу отчет для компании по формированию свода премий за выбранный период для выбранных структур. В отчете выводится ~9000 строк, при этом есть заголовки структур предприятия, есть депримированные сотрудники (выделяются красным цветом) и разнообразные промежуточные итоги. Отчет работает правильно, но вот скорость очень низкая, т.к. идет построчный вывод и форматирование.
Вывод в Excel через ADODB удовлетворительный по скорости, но вот с форматированием в процессе никак, только после вывода в Excel можно применить его на все выведенные данные.
Есть ещё способы создания отчетов с удовлетворительной скоростью и возможность форматировать "на лету" ?
Последний раз редактировалось: Константин (Сб Май 12, 2012 17:33), всего редактировалось 1 раз |
|
Вернуться к началу |
|
 |
Spartak
Зарегистрирован: 18.03.2010 Сообщения: 185
|
Добавлено: Сб Май 05, 2012 15:12 Заголовок сообщения: |
|
|
Попробуйте посмотрите отчет в зарплате Документы - Ведомости - Начислений на выплаты, он кажется имеет довольно сложное форматирование... |
|
Вернуться к началу |
|
 |
VladSPb
Зарегистрирован: 27.04.2012 Сообщения: 17 Откуда: St.Petersburg
|
Добавлено: Пн Май 07, 2012 13:24 Заголовок сообщения: |
|
|
Самый быстрый вывод - это если в z-процедуре в запросе получать не набор полей, а 1 поле, содержащее конкатенацию всех полей (через спецразделитель). А в шаблоне д.б. макрос, разбирающий данные по столбцам. Тогла скорость вывода увеличится в разы, если не на порядки. Одно "но": при необходимости корректировки отчета - корректировка усложнится, т.к. надо будет ковырять и макрос...  |
|
Вернуться к началу |
|
 |
Константин
Зарегистрирован: 02.05.2012 Сообщения: 39 Откуда: Красноярск
|
Добавлено: Пт Май 11, 2012 19:54 Заголовок сообщения: |
|
|
Отчеты на Z-языке вроде быстрей, но так:
Код: |
local Query_ as string;
ADODB.Connection as AutoCon;
ADODB.Recordset as AutoSet;
ADODB.Recordset as AutoSet2;
AutoCon.Open('@@xUtil{dsq}');
AutoSet.CursorLocation = 2;
CON Формирование отчета "Список работников"...;
let Query_='select
pp.Num_Tab,
cc.Full_Name,
ap.Name_appoint,
stt.Struct_Name,
t1.name,
''=СУММ(1+3+5)''
from
user_standart_recipients t0
join people pp on t0.people_id=pp.pId
join card cc on pp.Auto_Card=cc.Auto_Card
join pr_current prc on pp.pId=prc.pId and GETDATE() between prc.Date_trans and prc.Date_depart
join Appointments ap on ap.Code_appoint=prc.Code_Appoint
join user_standart_pts t1 on t0.standart_id=t1.id
join StructS stt on stt.Struct_Code =prc.Code_struct_name
join Cells ccc on ccc.Cell_item = prc.Cell_item
order by t1.pt,t0.standart_id,stt.sort,prc.poz,ccc.number';
AutoSet.Open(:Query_, :AutoCon, 3, 1, 1);
execute xOCX {Excel.Application as Excel};
AutoSet.Open(:Query_, :AutoCon, 100, 100, 1);
execute xOCX {Excel.Application as Excel};
local vb.Record=&AutoSet;
local vb.Excel=&Excel;
vb
{
Excel.ScreenUpdating = 0
Excel.EnableEvents = 0
Dim WorkBook
Set WorkBook=Excel.Workbooks.Add()
WorkBook.Worksheets(1).Cells(1,1) = "Таб"
WorkBook.Worksheets(1).Cells(2,1).CopyFromRecordset Record
WorkBook.Worksheets(1).Cells(1,2) = "ФИО"
WorkBook.Worksheets(1).Cells(2,2).CopyFromRecordset Record
WorkBook.Worksheets(1).Cells(1,3) = "Cnhernehf"
WorkBook.Worksheets(1).Cells(2,3).CopyFromRecordset Record
WorkBook.Worksheets(1).Rows(1).RowHeight = 30
WorkBook.Worksheets(1).Columns(1).ColumnWidth = 25
rem Меняем тип строчки на формулу
WorkBook.Worksheets(1).Columns(6).Select
rem WorkBook.Worksheets(1).Selection.Value = WorkBook.Selection.FormulaLocal
WorkBook.Worksheets(1).Columns(6).FormulaLocal = WorkBook.Worksheets(1).Columns(6).Value
Excel.ScreenUpdating = 1
Excel.EnableEvents = 1
};
AutoSet.Close;
CON;
execute xOCX{
Excel.Visible=True;
};
execute xOcxFree(AutoSet);
execute xOcxFree(Excel);
execute xOcxFree(AutoCon);
|
Скорость самая подходящая, только вот не могу разобраться как вывести в одну таблицу результат нескольких последовательныз запросов. Может кто сталкивался? |
|
Вернуться к началу |
|
 |
Константин
Зарегистрирован: 02.05.2012 Сообщения: 39 Откуда: Красноярск
|
Добавлено: Сб Май 12, 2012 09:30 Заголовок сообщения: |
|
|
(исправлено) По мотивам данного форума нашел следующее:
Код: |
--Быстрый вывод в Excel двух запросов, в каждом по 126000 записей
Local {_strQry; _Title; _Title1;};
Select short_name
into :Struct_name_
from setup where id_firm = 1;
Let {
_Title = 'asdqwe123';
};
Let {
_Title1 = Struct_name_[''] + ' Период:' +'_dateask_month[м]' + ' _dateask_year';
};
Alias _strQry := select
"Подразделение" = FNAme
,"ПФ(страх)" = h1
,"ПФ(накоп)" = h2
,"ПФ(всего)" = h4
,"ФСС" = h5
,"ТФОМС" = h6
,"ФФОМС" = h7
,"Травматизм" = h8
,"НДФЛ" = st
from user_rep
;
-- Параметры коннекта
Free _dsn,_db,_uid,_pwd,_is_ntuser,_ConnStr;
Local{_dsn;_db;_uid;_pwd;_is_ntuser;_ConnStr;};
Let _dsn = '@@xUtil{DSN}';
select db_name() into :_db;
select suser_sname() into :_uid;
Let _Pwd = '@@xUtil{pwd}';
select Count(*)
into :_is_ntuser
from master.dbo.syslogins
where loginname = suser_sname()
and (isntname =1 OR isntgroup = 1 OR isntuser = 1);
if _is_ntuser['] > 0 then
{Let _ConnStr := 'ODBC;DSN=' + _dsn[''] + ';UID=' + _uid[''] + ';PWD=;Database=' + _db[''];}
else {Let _ConnStr := 'ODBC;DSN=' + _dsn[''] + ';UID=' + _uid[''] + '; PWD=' + _pwd[''] + ';Database=' + _db['']};
Free _dsn,_db,_uid,_pwd,_is_ntuser;
-- Выгрузка данных
VB.FREE;
VB{
Dim ConnStr
Dim strQry
Dim TitleTxt
Dim TitleTxt1
Dim Flag
};
Let VB.ConnStr := _ConnStr[""];
Let VB.strQry := _strQry[""];
Let VB.TitleTxt := _Title[""];
Let VB.TitleTxt1 := _Title1[""];
Alias VB.Flag == 0;
VB {
Flag = 0
Dim cc
Dim lc
Dim Excel
Dim Sh
Err.Clear
On Error Resume Next
Set Excel = GetObject(,"Excel.Application")
If Err.Number <> 0 Then
Err.Clear
Set Excel = CreateObject("Excel.Application")
end if
On Error Goto 0
Excel.Visible = True
rem Excel.Workbooks.Add
Set Sh = GetObject("", "Excel.sheet")
Set Sh = Sh.sheets(1)
Sh.PageSetup.Orientation = 2
Sh.PageSetup.Zoom = False
Sh.PageSetup.FitToPagesWide = 1
Sh.PageSetup.FitToPagesTall = 1
With Sh.QueryTables.Add(ConnStr, Sh.Range("A3"))
.Name = "ExportData"
.CommandText = strQry
.FieldNames = True
rem .RowNumbers = false
rem .FillAdjacentFormulas = False
rem .PreserveFormatting = True
rem .RefreshOnFileOpen = False
rem .BackgroundQuery = False
rem .RefreshStyle = 1
rem .SavePassword = False
rem .SaveData = True
rem .AdjustColumnWidth = True
rem .RefreshPeriod = 0
rem .EnableEditing = False
rem .PreserveColumnInfo = True
.Refresh
End With
With Sh.QueryTables.Add(ConnStr, Sh.Range("L3"))
.Name = "ExportData"
.CommandText = strQry
.FieldNames = True
rem .RowNumbers = false
rem .FillAdjacentFormulas = False
rem .PreserveFormatting = True
rem .RefreshOnFileOpen = False
rem .BackgroundQuery = False
rem .RefreshStyle = 1
rem .SavePassword = False
rem .SaveData = True
rem .AdjustColumnWidth = True
rem .RefreshPeriod = 0
rem .EnableEditing = False
rem .PreserveColumnInfo = True
.Refresh
End With
cc = Sh.UsedRange.Columns.Count
While cc = 0
cc = Sh.UsedRange.Columns.Count
wend
if Sh.UsedRange.Rows.Count > 1 then
Sh.UsedRange.Select
Excel.Selection.Borders(5).LineStyle = -4142
Excel.Selection.Borders(6).LineStyle = -4142
With Excel.Selection.Borders(7)
.LineStyle = 1
.Weight = 2
.ColorIndex = -4105
End With
With Excel.Selection.Borders(8)
.LineStyle = 1
.Weight = 2
.ColorIndex = -4105
End With
With Excel.Selection.Borders(9)
.LineStyle = 1
.Weight = 2
.ColorIndex = -4105
End With
With Excel.Selection.Borders(10)
.LineStyle = 1
.Weight = 2
.ColorIndex = -4105
End With
With Excel.Selection.Borders(11)
.LineStyle = 1
.Weight = 2
.ColorIndex = -4105
End With
With Excel.Selection.Borders(12)
.LineStyle = 1
.Weight = 2
.ColorIndex = -4105
End With
End If 'if Sh.UsedRange.Rows.Count
cc = Sh.UsedRange.Columns.Count
Sh.Range(Sh.Cells(3, 1), Sh.Cells(3, cc)).Select
With Excel.Selection.Interior
.ColorIndex = 15
.Pattern = 1
End With
With Excel.Selection
.HorizontalAlignment = -4108
.VerticalAlignment = -4160
.WrapText = True
.Orientation = 0
.AddIndent = False
.ShrinkToFit = False
.MergeCells = False
End With
Excel.Selection.WrapText = True
Excel.Selection.ColumnWidth = 10
Excel.Columns("A:A").ColumnWidth = 40
Excel.Columns("B:B").ColumnWidth = 14
Excel.Columns("C:C").ColumnWidth = 14
Excel.Columns("D:D").ColumnWidth = 14
Excel.Columns("E:G").ColumnWidth = 14
Excel.Columns("H:H").ColumnWidth = 14
Excel.Columns("I:I").ColumnWidth = 14
Excel.Columns("E:H").WrapText = True
Excel.Columns("A:H").VerticalAlignment = -4160
Sh.Range("A1").Value = TitleTxt
Sh.Range("A1").Select
Sh.Range(Sh.Cells(1, 1), Sh.Cells(1, cc)).Select
Excel.Selection.Font.Bold = True
Excel.Selection.Font.Size = Excel.Selection.Font.Size
Sh.Range("A2").Value = TitleTxt1
Sh.Range("A2").Select
Excel.Selection.Font.Bold = True
Excel.Selection.Font.Size = Excel.Selection.Font.Size
Sh.Range(Sh.Cells(4, 3), Sh.Cells(99, 9)).Select
Excel.Selection.NumberFormat = "#,##0.00"
Sh.Range("A2").Select
Set Excel = Nothing 'Добавил, после найденного решения
Flag = 1
};--VB
VB.FREE;
free *;
EndFn:
|
В одну таблицу выводится два запроса с достаточно большим кол-вом строк, но минус в том что после выполнения скрипта и закрытия сформированного документа в памяти остается висеть процесс Excel. Не могу понять какую переменную надо освободить, что бы Excel не висел после закрытия.
Последний раз редактировалось: Константин (Сб Май 12, 2012 10:23), всего редактировалось 1 раз |
|
Вернуться к началу |
|
 |
Mike Большой шоколадный орден

Зарегистрирован: 07.04.2011 Сообщения: 255
|
Добавлено: Сб Май 12, 2012 09:45 Заголовок сообщения: |
|
|
execute xOCXfree(*);
ан нет, чтот и у меня висеть продолжает... |
|
Вернуться к началу |
|
 |
Константин
Зарегистрирован: 02.05.2012 Сообщения: 39 Откуда: Красноярск
|
Добавлено: Сб Май 12, 2012 09:51 Заголовок сообщения: |
|
|
Mike не помогает. Пробовал на Express версии босса, Excel 2010
Решение найдено:
в конце блока VB надо добавить:
|
|
Вернуться к началу |
|
 |
Константин
Зарегистрирован: 02.05.2012 Сообщения: 39 Откуда: Красноярск
|
Добавлено: Сб Май 12, 2012 13:41 Заголовок сообщения: |
|
|
Сделал такой пример, демонстрирующий subj
Код: |
--Подготовим тестовые данные
erroroff;
DROP TABLE tmp_20120412_1;
DROP TABLE tmp_20120412_2;
erroron;
create table tmp_20120412_1 (str_code int, str_name nvarchar(50));
create table tmp_20120412_2 (id int, fio_name nvarchar(50), str_code int);
insert into tmp_20120412_1 (str_code,str_name) VALUES ('1','Дирекция');
insert into tmp_20120412_1 (str_code,str_name) VALUES ('2','Инженеры');
insert into tmp_20120412_1 (str_code,str_name) VALUES ('3','Рабочие');
insert into tmp_20120412_2 (id,fio_name,str_code) VALUES ('1','Вася А','1');
insert into tmp_20120412_2 (id,fio_name,str_code) VALUES ('2','Вася Б','1');
insert into tmp_20120412_2 (id,fio_name,str_code) VALUES ('3','Петя А','2');
insert into tmp_20120412_2 (id,fio_name,str_code) VALUES ('4','Петя Б','2');
insert into tmp_20120412_2 (id,fio_name,str_code) VALUES ('5','Миша А','3');
insert into tmp_20120412_2 (id,fio_name,str_code) VALUES ('6','Миша Б','3');
insert into tmp_20120412_2 (id,fio_name,str_code) VALUES ('7','Жора А','3');
insert into tmp_20120412_2 (id,fio_name,str_code) VALUES ('8','Жора Б','3');
insert into tmp_20120412_2 (id,fio_name,str_code) VALUES ('9','Боря А','3');
insert into tmp_20120412_2 (id,fio_name,str_code) VALUES ('10','Боря Б','3');
-- Параметры коннекта
Free _dsn,_db,_uid,_pwd,_is_ntuser,_ConnStr;
Local {_dsn;_db;_uid;_pwd;_is_ntuser;_ConnStr;};
Let _dsn = '@@xUtil{DSN}';
select db_name() into :_db;
select suser_sname() into :_uid;
Let _Pwd = '@@xUtil{pwd}';
select Count(*) into :_is_ntuser from master.dbo.syslogins where loginname = suser_sname() and (isntname =1 OR isntgroup = 1 OR isntuser = 1);
if _is_ntuser['] > 0
then {Let _ConnStr := 'ODBC;DSN=' + _dsn[''] + ';UID=' + _uid[''] + ';PWD=;Database=' + _db[''];}
else {Let _ConnStr := 'ODBC;DSN=' + _dsn[''] + ';UID=' + _uid[''] + '; PWD=' + _pwd[''] + ';Database=' + _db['']};
Free _dsn,_db,_uid,_pwd,_is_ntuser;
-- Начало вывода результата в Excel
VB.FREE;
VB{
Dim ConnStr
Dim str_query
Dim Flag
};
Let VB.ConnStr := _ConnStr[""];
Alias VB.Flag == 0;
VB {
Flag = 0
Dim cc
Dim lc
Dim Excel
Dim Sh
Dim CurPosY
Dim SeekY
Dim st_name
Err.Clear
On Error Resume Next
Set Excel = GetObject(,"Excel.Application")
If Err.Number <> 0 Then
Err.Clear
Set Excel = CreateObject("Excel.Application")
end if
On Error Goto 0
Excel.Visible = True
rem Excel.Workbooks.Add
Set Sh = GetObject("", "Excel.sheet")
Set Sh = Sh.sheets(1)
Sh.PageSetup.Orientation = 2
rem Sh.PageSetup.Zoom = False
rem Sh.PageSetup.FitToPagesWide = 1
rem Sh.PageSetup.FitToPagesTall = 1
Excel.ActiveWindow.WindowState = -4137 ' на весь жкран развернуть
};
stable @structs select str_code,str_name from tmp_20120412_1;
let vb.CurPosY=1; --Положение курсора в таблице
let vb.SeekY=0; -- Кол-во записей возвращаемых запросом
--Перебираем структуру предприятия
scan @structs
execute {
alias astr_query = select ROW_NUMBER() OVER(ORDER BY id),fio_name,str_code from tmp_20120412_2 where str_code=@structs:1; -- запрос получения списка сотрудников в подразделении
let vb.str_query := astr_query[""]; --передаем параметр в объект VB
let vb.st_name := @structs:2; -- передаем в VB наименвоание подразделения
--для смещения вниз необходимо знать кол-во записей в запросе
stable @lenquery astr_query;
let vb.seeky := @lenquery:[x];
destroy @lenquery;
--добавляем в таблицу точки вывода запроса, сами запросы
VB {
'добавляем некое подобие шапки, прежде объединив их
sh.Range(sh.Cells(CurPosY,1), sh.Cells(CurPosY,3)).MergeCells = True
sh.Cells(CurPosY,1) = st_name
CurPosY = CurPosY + 1
With Sh.QueryTables.Add(ConnStr, Sh.Range(sh.cells(CurPosY,1),sh.cells(CurPosY+seeky,3)))
.Name = "ExportData"
.CommandText = str_query
.FieldNames = false 'не выводить наименовая полей
.RefreshStyle = 0 'не смещать данные при добавлении в область ранее добавленных данных, если 1 то будет смещать
.Refresh
End With
CurPosY = CurPosY + seeky 'сдвигаем курсор таблицы на размер добавляемых данных
};
};
destroy @structs;
VB {
flag=1
set Excel = nothing
};--VB
VB.FREE;
|
На исходной задачи опробовал, скорость формирования отчета приемлемая.
joy! _________________ return @@tMonth[%m] |
|
Вернуться к началу |
|
 |
|
|
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах
|
|