:: Visual Foxpro, Foxpro for DOS
загрузка xml в excel
danton1973
Автор

Сообщений: 122
Откуда: Пермь
Дата регистрации: 10.08.2020
При загрузке таким образом:
WITH .ActiveWorkbook
.XmlMaps.ADD(FORCEEXT(m.tcXMl,"xsd"),"VFPData").NAME=m.lcXMLMapName
.XmlImport(m.tcXMl,.XmlMaps(m.lcXMLMapName),,.ActiveSheet.Cells(m.lnRow,1))
ENDWITH
получается таблица, где наименования полей расположены в одной строчке, значения в колонках под ними.
Пытаюсь сделать, что бы наименования полей были расположены в одной колонке, а значения - в строчках справа от них
aFieldPrint - список полей для выгрузки в виде aFieldPrint[i,1] - имя поля таблицы, aFieldPrint[i,2] - имя поля в выгрузке
Пример aFieldPrint[1,1] = "Saldo", aFieldPrint[1,2] = "Остаток_в_ИРК 20-1"
.ActiveWorkbook.XmlMaps.ADD(FORCEEXT(m.tcXml,"xsd"),"VFPData").NAME=m.lcXMLMapName
m.loXMLMap=.ActiveWorkbook.XmlMaps(m.lcXMLMapName)
FOR m.i=1 TO m.lnCountField
.RANGE(.Cells(m.i+m.lnRow,2),.Cells(m.i+m.lnRow,2)).XPath.SetValue(m.loXMLMap,"/VFPData/"+m.tcCursor+'/'+THISFORM.aFieldPrint[m.i,2])
.Cells(m.i+m.lnRow,1).VALUE=THISFORM.aFieldPrint[m.i,2]
NEXT
.ActiveWorkbook.XmlImport(m.tcXml,m.loXMLMap)
Импорт происходит без ошибок, но с одним НО: импортируется только первая запись из файла xml!
Какие мысли имеются?
У функции WorksheetFunction.Transpose имеются ограничения, которые делают её использование не возможной... :-(
Ratings: 0 negative/0 positive
Re: загрузка xml в excel
sphinx

Сообщений: 30760
Откуда: Каменск-Уральски
Дата регистрации: 22.11.2006
А если пойти другим путем - загрузить данные из XML в курсор (через XMLAdapter), потом перегрузить данные в массив (SELECT... INTO ARRAY), а затем полученный массив вставить на лист.

Или через ODBC подключиться к XML и также выгрузить сначала в курсор, потом в массив, массив на лист.


------------------
"Veni, vidi, vici!"(с)
Ratings: 0 negative/0 positive
Re: загрузка xml в excel
danton1973
Автор

Сообщений: 122
Откуда: Пермь
Дата регистрации: 10.08.2020
До меня в программе было реализована прямая запись в ячейки. Однако попытка загрузки более 5000 записей в Excel длилась больше двух часов. Так что и через массив будет долго. А данные как раз из курсора и грузятся.
WITH THISFORM.oExcel
.WorkBooks.ADD
.DisplayAlerts=False
.VISIBLE= .F.
.WINDOWSTATE = xlMinimized
FOR m.lnCounter=.Sheets.COUNT TO 2 STEP -1
.Sheets(m.lnCounter).DELETE
NEXT
WITH .Sheets(1)
.SELECT
ENDWITH
.ActiveWindow.DisplayGridLines=False
FOR m.i=1 TO m.lnCountField
m.lnRow=3
.RANGE(.Cells(m.lnRow,m.i),.Cells(m.lnRow,m.i)).COLUMNS.EntireColumn.AUTOFIT
m.lnCounter=ASCAN(THISFORM.faName,laFieldList[m.i,1])
IF m.lnCounter#0
m.lcField=THISFORM.faHeader[m.lnCounter]
ELSE
m.lcField=ALLTRIM(STRTRAN(laFieldList(m.i,1),'_',' '))
ENDIF
m.lnCounter=41
.Cells(m.lnRow,m.i).VALUE=m.lcField
m.lnColWidth=LEN(m.lcField)+1
DO CASE
CASE laFieldList[m.i,2]=='C'
m.lnColWidth=MIN(41,LEN(ALLTRIM(laFieldList[m.i,1])))
CASE laFieldList[m.i,2]=='M'
m.lnALen=MEMLINES(m.lcField)
FOR m.y=1 TO m.lnALen
m.lnCounter=MAX(m.lnCounter,LEN(ALLTRIM(MLINE(m.lcField,m.y))))
NEXT
m.lnColWidth=MIN(41,m.lnCounter)
CASE INLIST(laFieldList[m.i,2],'N','I','F','O','Y')
m.lnColWidth=MAX(m.lnColWidth,laFieldList[m.i,3]+laFieldList[m.i,4]+2)
ENDCASE
WITH .RANGE(.Cells(m.lnRow,m.i),.Cells(m.lnRow,m.i))
.HorizontalAlignment = xlGeneral
.VerticalAlignment = xlCenter
.WrapText = .T.
WITH .BORDERS(xlEdgeBottom)
.Weight=xlMedium
.LineStyle=xlContinuous
ENDWITH
WITH .BORDERS(xlEdgeTop)
.Weight=xlMedium
.LineStyle=xlContinuous
ENDWITH
WITH .BORDERS(xlEdgeRight)
.Weight=xlMedium
.LineStyle=xlContinuous
ENDWITH
WITH .BORDERS(xlEdgeLeft)
.Weight=xlMedium
.LineStyle=xlContinuous
ENDWITH
ENDWITH
m.lcField=GetExcelCol(i)
WITH .RANGE(m.lcField+":"+m.lcField)
.SELECT
.COLUMNWIDTH = m.lnColWidth*1.2
ENDWITH
NEXT
m.lnCounter=RECCOUNT()
SCAN
m.lnRow=m.lnRow+1
loPB.UPDATE(INT(m.lnRow*100/m.lnCounter),"Âûãðóçêà â Excel")
FOR m.i=1 TO m.lnCountField
IF ASCAN(THISFORM.faName,laFieldList[m.i,1])#0
m.lcField=laFieldList[m.i,1]
ELSE
m.lcField=ALLTRIM(STRTRAN(laFieldList(m.i,1),'_',' '))
ENDIF
m.lcField=_VFP.EVAL(laFieldList[m.i,1])
DO CASE
CASE laFieldList[m.i,2]=='C'
WITH .Cells(m.lnRow,m.i)
.NumberFormat='@'
.VALUE=THISFORM.createSbor(ALLTRIM(m.lcField),@laFields)
ENDWITH
CASE laFieldList[m.i,2]=='M'
WITH .Cells(m.lnRow,m.i)
.NumberFormat='@'
.VALUE=ALLTRIM(m.lcField)
ENDWITH
CASE INLIST(laFieldList[m.i,2],'N','I','F','O','Y')
WITH .Cells(m.lnRow,m.i)
m.lcStr=IIF(laFieldList[m.i,3]#0,'.'+REPLICATE('0',laFieldList[m.i,4]),'')
.NumberFormat="0"+m.lcStr+";[Red]-0"+m.lcStr
.VALUE=NTrim(m.lcField,laFieldList[m.i,3],laFieldList[m.i,4])
ENDWITH
CASE INLIST(laFieldList(m.i,2),'D','T')
WITH .Cells(m.lnRow,m.i)
.NumberFormat="dd.mm.yyyy"
.VALUE=NTrim(m.lcField)
ENDWITH
CASE laFieldList(m.i,2)=='L'
WITH .Cells(m.lnRow,m.i)
.NumberFormat='@'
.VALUE=IIF(m.lcField,"Äà","Íåò")
ENDWITH
OTHERWISE
WITH .Cells(m.lnRow,m.i)
.VALUE=ALLTRIM(m.lcField)
ENDWITH
ENDCASE
.RANGE(.Cells(m.lnRow,m.i),.Cells(m.lnRow,m.i)).COLUMNS.EntireColumn.AUTOFIT
WITH .RANGE(.Cells(m.lnRow,m.i),.Cells(m.lnRow,m.i))
.HorizontalAlignment = xlGeneral
.VerticalAlignment = xlTop
.WrapText = .T.
WITH .BORDERS(xlEdgeBottom)
.Weight=xlThin
.LineStyle=xlContinuous
ENDWITH
WITH .BORDERS(xlEdgeTop)
.Weight=xlThin
.LineStyle=xlContinuous
ENDWITH
WITH .BORDERS(xlEdgeRight)
.Weight=xlThin
.LineStyle=xlContinuous
ENDWITH
WITH .BORDERS(xlEdgeLeft)
.Weight=xlThin
.LineStyle=xlContinuous
ENDWITH
ENDWITH
NEXT
ENDSCAN
Ratings: 0 negative/0 positive
Re: загрузка xml в excel
Joys

Сообщений: 3483
Откуда: Старая Русса
Дата регистрации: 25.06.2000
danton1973
Однако попытка загрузки более 5000 записей в Excel длилась больше двух часов. Так что и через массив будет долго.
Попробуйте через буфер обмена
сформируйте данные построчно
"Заголовок"+CHR(9)+"Значение"+CHR(13)

потом все в _CLIPTEXT
потом в excel
ActiveSheet.Paste
Ratings: 0 negative/0 positive
Re: загрузка xml в excel
akvvohinc

Сообщений: 4001
Откуда: Москва
Дата регистрации: 11.11.2008
danton1973
Так что и через массив будет долго
Смысл предложения "через массив" не в том, откуда в Excel заносятся данные - из курсора или массива, а в самом способе заполнения ячеек.
У вас он поячеечный - то есть при большом количестве данных быстрее наступит даже "отложенная" пенсия, чем окончание этой процедуры.
Способ "через массив" подразумевает, что за "один раз" записывается сразу множество ячеек - все элементы массива.

На форуме эта тема поднималась множество раз - поищите.
Ratings: 0 negative/0 positive
Re: загрузка xml в excel
ssa

Сообщений: 12951
Откуда: Москва
Дата регистрации: 23.03.2005
danton1973
До меня в программе было реализована прямая запись в ячейки.
То есть выбран был самый медленный способ.
Цитата:
Однако попытка загрузки более 5000 записей в Excel длилась больше двух часов.
Разумеется.
Цитата:
Так что и через массив будет долго.
А вот это очень спорное утверждение, которое говорит об очень слабой проработке вопроса. Ибо загрузка через массив уже неоднократно доказывала свою значительно большую скорострельность по сравнению со способом поячеечной записи.
Цитата:
А данные как раз из курсора и грузятся.
Вот и прелестно! Кидаем из курсора в массив, а из него уже в Excel. Способ давно известный и практически доказавший свою стабильность, скорострельность и т.д.

------------------
Лень - это неосознанная мудрость.
Ratings: 0 negative/2 positive
Re: загрузка xml в excel
Ydin

Сообщений: 7640
Откуда: Киев
Дата регистрации: 16.12.2005
В свое время проверял.
С Икселом надо помнить, что в цикле по одной команде всегда будет долго, т.к. этот сам сам вызов берет время.
Через карман или массив - это один вызов!
Я пользуюсь этими двумя способами. У меня свой построитель отчета из макета.
Там везде пытаюсь сократить количество обращений к Иксел.
С Вордом, кстати, аналогично
Ratings: 0 negative/0 positive
Re: загрузка xml в excel
danton1973
Автор

Сообщений: 122
Откуда: Пермь
Дата регистрации: 10.08.2020
SourceArray = loSourceWS.RANGE(loSourceWS.Cells(m.lnRow + 1, 1), loSourceWS.Cells(m.lnRow + m.lnReccount + 1, m.lnCountField)).VALUE
loTargetWS.ACTIVATE
loTargetWS.RANGE(loTargetWS.Cells(m.lnRow + 1, 1), loTargetWS.Cells(m.lnRow + m.lnCountField, m.lnReccount + 1)).VALUE = WorksheetFunction.Transpose(SourceArray)
Массив транспонитует, но , почему-то, заполняет его только значением первой ячейки... :-(
SourceArray - нормальный такой массив получается...
А в Excel эти же команды отрабатывают как надо...
Ratings: 0 negative/0 positive
Re: загрузка xml в excel
AndyNigmatec

Сообщений: 1407
Откуда: Волгоград
Дата регистрации: 28.06.2015
что касается экспорта из табл/курсора в excel, то здесь уже давно приводили трюк:

поскипал, общий принцип:

loExcel=CREATEOBJECT("EXCEL.APPLICATION")
loSheet = loExcel.Workbooks(lcWbName).Sheets(1)
SELECT * FROM (lcAlias) INTO ARRAY laData
lcRowsData=ALEN(laData,1)
lcColumnsData=ALEN(laData,2)
loSheet.Cells(2,1).Resize(lcRowsData, lcColumnsData).Value = FpassArray('laData')
...
*******************************
FUNCTION FpassArray
LPARAMETERS tcArrayName
* Трюк для передачи массива данных обратно в диапазон ячеек Excel.
RETURN @&tcArrayName

работает очень быстро



Исправлено 1 раз(а). Последнее : AndyNigmatec, 14.12.22 14:00
Ratings: 0 negative/0 positive
Re: загрузка xml в excel
akvvohinc

Сообщений: 4001
Откуда: Москва
Дата регистрации: 11.11.2008
Кстати, в Фоксе нет команды копирования массива, но с помощью того же трюка это можно делать:
CLEAR
DIMENSION array1[3]
array1 = 1
array2 = arrayref('array1') && создание массива с копированием элементов другого массива
array2[2] = 222 && чтобы убедиться, что array2 - не просто новая ссылка на массив array1
DISPLAY MEMORY LIKE array*
FUNCTION arrayref
PARAMETERS arrayname
RETURN @&arrayname

Этот пример показывает, что функция arrayref возвращает не просто ссылку на массив, имя которого в неё передано, а ссылку на копию этого массива.
(но это лишь моя интерпретация происходящего)

Жаль, что с объектами такой финт не проходит.



Исправлено 3 раз(а). Последнее : akvvohinc, 14.12.22 17:23
Ratings: 0 negative/0 positive
Re: загрузка xml в excel
danton1973
Автор

Сообщений: 122
Откуда: Пермь
Дата регистрации: 10.08.2020
не совсем понял "отсутствие функции копирования массива"?
ACOPY чем не устраивает?
Ratings: 0 negative/0 positive
Re: загрузка xml в excel
danton1973
Автор

Сообщений: 122
Откуда: Пермь
Дата регистрации: 10.08.2020
AndyNigmatec
что касается экспорта из табл/курсора в excel, то здесь уже давно приводили трюк:
поскипал, общий принцип:

loExcel=CREATEOBJECT("EXCEL.APPLICATION")
loSheet = loExcel.Workbooks(lcWbName).Sheets(1)
SELECT * FROM (lcAlias) INTO ARRAY laData
lcRowsData=ALEN(laData,1)
lcColumnsData=ALEN(laData,2)
loSheet.Cells(2,1).Resize(lcRowsData, lcColumnsData).Value = FpassArray('laData')
...
*******************************
FUNCTION FpassArray
LPARAMETERS tcArrayName
* Трюк для передачи массива данных обратно в диапазон ячеек Excel.
RETURN @&tcArrayName

работает очень быстро

У меня проблема не передать данные массива в Excel, а именно траспонировать его



Исправлено 1 раз(а). Последнее : danton1973, 15.12.22 06:30
Ratings: 0 negative/0 positive
Re: загрузка xml в excel
AndyNigmatec

Сообщений: 1407
Откуда: Волгоград
Дата регистрации: 28.06.2015
danton1973
У меня проблема не передать данные массива в Excel, а именно траспонировать его

Мне такого не требовалось, но в чем проблема то сделать это средствами самого excel?

навскидку:
1. выводим данные на лист Sheets(1) вышеописанным способом через массив,
ну т.е.
loExcel=CREATEOBJECT("EXCEL.APPLICATION")
loSheet = loExcel.Workbooks(lcWbName).Sheets(1)
loSheet2 = loExcel.Workbooks(lcWbName).Sheets(2)
и т.д. ...
соотв. диапазон нам известен - это lcRowsData, lcColumnsData
второй лист (или даже другой файл можно - на выбор) нам понадобится чтобы вставить транспонируемое

2. далее этот вставленный диапазон копируем и вставляем с транспонированием на другой лист/книгу
#DEFINE xlPasteAll -4104
#DEFINE xlNone -4142
with loSheet
.Range(.Cells(1,1), .Cells(lcRowsData, lcColumnsData)).Copy
endwith
with loSheet2
.Cells(1,1).PasteSpecial(xlPasteAll, xlNone, .F., .T.)
endwith

в PasteSpecial() нужно поиграть-прописать параметры, в VBA так

.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= False, Transpose:=True


данный код не проверял - но думаю где-то так должно вполне сработать ))



Исправлено 2 раз(а). Последнее : AndyNigmatec, 15.12.22 09:43
Ratings: 0 negative/0 positive
Re: загрузка xml в excel
danton1973
Автор

Сообщений: 122
Откуда: Пермь
Дата регистрации: 10.08.2020
Я пробовал этот вариант, НО: несколько тысяч записей при нескольких десятков полей.... На старых компах Excel просто трапается...
в общем: решил я эту проблему через создание bas-файла с последующей его загрузкой и выполнением его в само Excel
.EnableEvents= .F.
.ScreenUpdating = .F.
.DisplayAlerts = .F.
m.loVBComponent=.ActiveWorkBook.VBProject.VBComponents.IMPORT(m.lcFile)
.APPLICATION.RUN("'"+.ActiveWorkBook.NAME+"'!CreateXMLList")
.ActiveWorkBook.VBProject.VBComponents.REMOVE(m.loVBComponent)
Ratings: 0 negative/0 positive
Re: загрузка xml в excel
akvvohinc

Сообщений: 4001
Откуда: Москва
Дата регистрации: 11.11.2008
Цитата:
ACOPY чем не устраивает?
Всё верно - это сработала моя "историческая память", ведь ACOPY() был не всегда, хотя появился ещё в FPD.
Ratings: 0 negative/0 positive
Re: загрузка xml в excel
AndyNigmatec

Сообщений: 1407
Откуда: Волгоград
Дата регистрации: 28.06.2015
ну так при работе с excel из фокса все это

.EnableEvents= .F.
.ScreenUpdating = .F.
.DisplayAlerts = .F.

а еще и .Visible=.f. подразумевается )))

и неск тыс записей - это сколько? До 10-15 тыс даже для старенького железа это не проблема

Не буду ни за что агитировать, нашли выход, он работает - значит хорошо.

Но я бы так не стал делать, создавать VBA, запускать его ... когда все решается двумя командами эксельке непосредственно из фокса, и кстати работать по скорости это должно так же - тут же работает сам excel, фокс тока команду дал



Исправлено 2 раз(а). Последнее : AndyNigmatec, 15.12.22 14:43
Ratings: 0 negative/0 positive
Re: загрузка xml в excel
akvvohinc

Сообщений: 4001
Откуда: Москва
Дата регистрации: 11.11.2008
danton1973
У меня проблема не передать данные массива в Excel, а именно траспонировать его
Напишите подробнее, в чем именно заключается ваша проблема траспонирования - вы же при выводе в Excel курсора с этим справляетесь.
Если даже просто выполнить аналогичные действия, но с выводом не напрямую в Excel, а сначала в массив, то в чем проблема?
Ratings: 0 negative/0 positive
Re: загрузка xml в excel
Ydin

Сообщений: 7640
Откуда: Киев
Дата регистрации: 16.12.2005
А что массив в Фоксе нельзя транспонировать?
Матрицу перевернуть очень легко. Или "транспонировать" это не то, что я думаю. Но в Высшей Алгебре это:

Dime la1(n1,n2)
* и заполнили уже
Dime la2(n2,n1)
for ln1=1 to n2
for ln2=1 to n1
la2(ln1,ln2) = ln1(ln2,ln1)
next
next

Мне кажется, что тут о чем-то другом...
Ratings: 0 negative/0 positive
Re: загрузка xml в excel
of63

Сообщений: 24629
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
> Матрицу перевернуть очень легко.

Золотые слова! Ну, если иметь ввиду "на угол 90 град", транспонировать.

() Но можно действительно повернуть на любой угол... И система уравнений, которую она представляет, останется также решаемой, и ее дискриминатнт... вроде... ( vmath.ru )
Это не по теме

По теме - надо пример файла, с которым надо что-то сделать, пример без секретных ОД, в небольшом размере. Если в большом размере, и подозрение именно в размере, то все равно хорошо бы посмотреть хоть что-то реальное... А то как об "утке" в амерском сленге, которая похожа "как"

Аа, виноватю Можно поворовачивать матрицы, имеющие физический образ (связанные друг с другом элементы, одинаковые размерности элементов матрицы). Произвольную таблицу (из разнородных элементов, можно "повернуть на 90 град" только "визуально"

()() Эрмитовы матрицы, Эххх
()()() и "собственные значения" матрицы (решения уравнения, которая она представляет в виде "диагональной" матрицы)


Вобщем, пример автор если даст, то попробуем...



Исправлено 5 раз(а). Последнее : of63, 16.12.22 00:46
Ratings: 0 negative/0 positive
Re: загрузка xml в excel
danton1973
Автор

Сообщений: 122
Откуда: Пермь
Дата регистрации: 10.08.2020
Требуется обычный поворот на 90, как написал товарищ Юдин. Просто в Excel это делается быстрее.
Я выше приводил пример кода, когда в Excel нормально транспонируется массив, а эти же команды из под VFP заполняют его значениями первой ячейки. :-(
Поэтому пришлось пойти на такое извращение.
Засовывать в массив кучу записей с длинными символьными полями и мемо полями... Ну я потестирую, конечно. Однако: "Сумлеваюсь я чего-то. Того и гляди: загремит, под фанфары!" (с)
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 19 (Гостей: 19)

© 2000-2023 Fox Club 
Яндекс.Метрика