Форум » [x]Harbour » Снова EXCEL (продолжение) » Ответить

Снова EXCEL (продолжение)

Dima: Ранее с Excel из Harbour ни когда не работал. Поставили тут задачу. У некоторых поставщиков есть определенные формы заказов. Набраны они в Excel. Сейчас народ руками заполняет эти формы и шлет по электронке поставщикам. Задача сводится к тому что бы в этих формах находить нужные коды товара и в нужной ячейке проставлять заказ. Может ткнет кто носом с чего начать что бы не напороться на грабли. Спасибо Сами формы тут http://zalil.ru/33279066

Ответов - 300, стр: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 All

Sergy: Dima пишет: Что касаемо картинки ....проделывал уже такой эксперимент , результат выше описал. Excel 2000 и 2010 при формате ДД.ММ.ГГ показывает все четко, год двумя цифрами. А вот если задать DD.MM.YY - любую дату преобразует в целое число (видно в строке формул вверху), а внутри ячейки пишет (дословно) "DD.MM.YY"

Oskar_AAA: Добрый день, коллеги. Программа на xHarbour, выгружаю файлы MS Excel, затем собираем в сводный отчет данные из выгруженных файлов MS Excel. Слетают настройки цветов и форматов в сводном отчете... Пробовал на разных версиях MS Excel, закономерности пока не нашел. Но на 1 ПК всегда выгружается без сбоев.Операционные системы на всех ПК - Win7, офис возможно разный... Что может быть в тонкостях настройки MS Excel? Всех со "Старым" Новым Годом!!!

Sadstar2016: Help me pls. Длительное время работает такая схема формирования отчета в Excel 1.Грузится xls-файл - образец с отформатированной шапкой (соответственно - нужные ширины столбцов) Чтобы не портить образец ( юзера всегда умудрятся его перезаписать) 2.Копируется лист 3.Создается новая книга. 4.Вставка в лист новой книги. 5.Добавление строк отчета в новую книгу oExcel:Workbooks:Open(cFile) oBook:=oExcel:ActiveWorkbook() oBook:Worksheets(1):Cells:Copy() oBookN:=oExcel:WorkBooks:Add() //новая пустая книга oSheet:=oBookN:Worksheets(1) oSheet:Paste() Вдруг с некоторых пор на одном рабочем месте перестали копироваться ширины столбцов. Пытался найти отличия в настройках Excel-я влияющие на режим копирования - не нашел. Второй вариант - принудительное копирование ширин столбцов. В макросе это выглядит так Cells.Select Selection.Copy Workbooks.Add ActiveSheet.Paste //вставка ширин столбцов Selection.PasteSpecial Paste:=xlPasteColumnWidths, Operation:=xlNone, SkipBlanks:=False, Transpose:=False Как последнюю строку макроса переписать в терминах Харбора?


Петр: Пробуйте так (не проверял) #define xlPasteColumnWidths 8 #define xlPasteSpecialOperationNone -4142 Paste := oExcel:ActiveSheet():PasteSpecial(xlPasteColumnWidths, xlPasteSpecialOperationNone, False, False)

Sadstar2016: Error 1559948/3 DISP_E_MEMBERNOTFOUND: PASTESPECIAL похоже - не находит метод PASTESPECIAL P.S. без ошибок прошло oSheet:Cells:PasteSpecial(xlPasteColumnWidths, xlPasteSpecialOperationNone, .f., .F.)

Петр: Sadstar2016 пишет: без ошибок прошло oSheet:Cells:PasteSpecial(xlPasteColumnWidths, xlPasteSpecialOperationNone, .f., .F.) Ну да, поскольку PasteSpecial в Excel метод обьекта Range, Cells: там нужен oExcel:ActiveSheet():Cells:PasteSpecial Петр пишет: Пробуйте так (не проверял) Но вы не об этом и спрашивали Как я понял, суть вопроса - как преобразовать вызов метода, а не к чему этот метод применить

MIKHAIL: Sadstar2016 пишет: 1.Грузится xls-файл - образец с отформатированной шапкой (соответственно - нужные ширины столбцов) Чтобы не портить образец ( юзера всегда умудрятся его перезаписать) Может проще скопировать файл шаблона и работать с ним?

Sadstar2016: IMHO - пусть юзер сам решает - где и под каким именем хранить файл - если его вообще нужно хранить

fil: На листе Excel создаю кнопку oExc:Sheets(1):Buttons:Add(120, 20+30*(cnt-1), 350, 22) и указываю макрос, который должен выполниться при клике на этой кнопке oExc:Sheets(1):Buttons(cnt):OnAction:="Макрос1" А как можно сделать вызов этого макроса с параметром ?

fil: Параметр, видимо, передать нельзя. Но можно использовать свойство кнопки Parameter, а в макросе поймать эту кнопку через Caller

TimTim: Нужно из xHarboura при заполнении Excel-файла задать формат поля "Денежный". Офис 2013. При вводе туда числа должен появляться символ ₽ ( Unicode 20BD ). Если сделать в самом Excel формат ячейки "Денежный" то все нормально. Кстати, этот новый символ рубля сидит на Правом Alt + 8. Попробовал вставить формат, который выдает макрос: Selection.NumberFormat = "#,##0.00 $" Переделал под xHarbour: NumberFormat := '# ##0,00 $ ' Добавляется только символ доллара в конце, что навело на мысль попробовать формат '# ##0,00 p.' с английской p, или HB_OemToAnsi( '# ##0,00 руб.' ). Все получилось, буковки появляются, числа можно складывать и т.д. Но все-таки, как быть с символом ₽?

Haz: TimTim пишет: Попробовал вставить формат, который выдает макрос: Selection.NumberFormat = "#,##0.00 $" макрос выдает другой формат при выборе значка рубля Selection.NumberFormat = "#,##0.00 [$?-419]" но OLE это тоже не понимает

Andrey: Всем привет ! Использую Ms Офис 2003 SP3. Периодически появляется дурацкая табличка: Как от неё избавиться ? Есть ли какой то флаг для этого сообщения ?

Dima: Andrey Погугли

Andrey: Dima пишет: Погугли Ничего для себя не нашёл. Методом проб и ошибок выяснил - неправильную работу в МиниГуи функции oBrw:Excel2(...) при вот вот таком формате вывода в Эксель: oBrw:aColumns[nJ]:cDataType := 'N' oBrw:aColumns[nJ]:cPicture := '99:99' Как исправить ?

Andrey: Обрезает нули в Екселе для текстового формата. Вывожу текстовые данные поля бд в ячейку - типа "0000345", указываю в ячейке формат: oSheet:Cells( nLine, nI ):SET( "NumberFormat", '@' ) // текстовая ячейка Как избавиться от обрезания ?

Dima: Поставь формат что то типа 0000000000 Где кол-во нулей равно длине строки в твоем случае 0000000

Andrey: Dima пишет: Поставь формат что то типа 0000000000 Спасибо ! Но тогда разрушается универсальность функции перекодировки Dbf->Xls. Текстовые данные могут быть разными. Я у себя делаю так: ............ cPole := aField[ nI , 1 ] xValue := FIELDGET( FIELDNUM( cPole ) ) // значени полей DBF nDecPole := FieldDec( FIELDNUM( cPole ) ) // для формата числа oSheet:Cells( nLine, nI ):Value := xValue IF FIELDTYPE( cPole ) == "C" oSheet:Cells( nLine, nI ):SET( "NumberFormat", '@' ) // текстовая ячейка ELSEIF FIELDTYPE( cPole ) == "N" IF nDecPole == 0 // значит целое число oSheet:Cells( nLine, nI ):SET( 'NumberFormat', '## ### ###0' ) // числовая ячейка ELSE oSheet:Cells( nLine, nI ):SET( 'NumberFormat', '## ### ###0,00' ) // числовая ячейка ENDIF ELSEIF FIELDTYPE( cPole ) == "D" oSheet:Cells( nLine, nI ):SET( "NumberFormat", 'm/d/yy' ) // дата ячейка ELSE oSheet:Cells( nLine, nI ):SET( "NumberFormat", '@' ) // текстовая ячейка ENDIF .....

Dima: Andrey Тогда читай https://support.office.com/ru-ru/article/%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0-%D0%BD%D0%B0%D1%87%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D1%85-%D0%BD%D1%83%D0%BB%D0%B5%D0%B9-%D0%B8-%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D1%81%D1%82%D1%8C-%D1%86%D0%B8%D1%84%D1%80%D0%BE%D0%B2%D1%8B%D1%85-%D0%BA%D0%BE%D0%B4%D0%BE%D0%B2-57f15d52-5c75-4a67-ad35-394ae944d347

Dima: Andrey пишет: IF FIELDTYPE( cPole ) == "C" oSheet:Cells( nLine, nI ):SET( "NumberFormat", '@' ) // текстовая ячейка а вот тут нужна доп проверка а не цифры ли там одни живут и если так то NumberFormat будет другим. PS По ходу не нашел (может искал плохо или еще что ) такой функции "а не цифры ли там одни живут" , так что придется лепить свою.

Haz: Andrey пишет: Я у себя делаю так: Попробуй сначала задать формат а потом присвоить значение в ячейку

Dima: Haz пишет: Попробуй сначала задать формат а потом присвоить значение в ячейку Работает однако.

Dima: Может и была тема , не нашел. Нужно через Ole , иметь возможность только смотреть и печатать документ Excel. PS Сам документ формируется с установкой пароля на изменение. С этим нет проблем.

Pasha: Можно вызвать метод: Sheet:PrintPreview()

Dima: Pasha пишет: Можно вызвать метод: Sheet:PrintPreview() Да не плохой вариант , но если закрыть Preview то снова окажусь в Excel а там делай что хош.

Pasha: А если так: Excel:Visible := .t. Sheet:PrintPreview() Excel:Visible := .f.

Dima: Pasha пишет: Excel:Visible := .f. Заработало Спасибо

Pasha: В office 2013 и office 2010 с последними обновлениями появилась новая неприятная хворь: При открытии документа методом Excel:Workbooks:Open происходит или ошибка открытия, или зависание при выполнении метода. Хворь проявляется у Excel, и иногда у Word. У меня шаблоны документов хранятся на letodb сервере. Перед открытием я их копирую в папку temp из getenv('temp'). Причем одни шаблоны могут открываться нормально (это Word), а другие - нет. С Excel ситуация такая: после открытия документа он заполняется, и остается на экране для дальнейших действий с ним пользователя. Пользователь что-то с ним делает (печатает), и закрывает Excel. Оказывается, что процесс Excel остается висеть в памяти, а шаблон в папке Temp залочен им, и последующее открытие этого шаблона невозможно. Причем, такая ситуация проявляется нестабильно: два раза Excel может закрыться нормально, а на третий - затык. Если не переписывать файлы в папку temp, а хранить их в другой папке, то хворь не проявляется совсем. Иногда хворь проходит, если пошаманить с таким бубном: "Откройте вкладку Файл, чтобы переключиться в представление Microsoft Office Backstage. В меню Справка выберите пункт Параметры; отобразится диалоговое окно Параметры. Щелкните элемент Центр управления безопасностью и нажмите кнопку Параметры центра управления безопасностью. В центре управления безопасностью щелкните пункт Параметры блокировки файлов. Установите флажок Открывать выбранные типы файлов в режиме защищенного просмотра и разрешить редактирование." Но такие танцы с бубном помогают не во всех случаях. Пока я выкручиваюсь заменой магической заколдованной папки temp на другую папку, а там кто знает, как эта хворь будет вести себя дальше. Если занемог Office 2010 и обновлениями, то помогает его снос и установка версии с диска и отключением обновлений. У Office 2013 хворь врожденная.

Dima: Pasha пишет: Перед открытием я их копирую в папку temp из getenv('temp') Тоже так делаю , но в папке Temp создаю свою папку и уже копирую в нее , проблем не было ни разу. PS Office 2003

Pasha: проблем не было ни разу. Значит, жди сюрпризов с новыми офисами.

Dima: Pasha Ключевая фраза "в папке Temp создаю свою папку и уже копирую в нее" , может и у тебя сработает кто знает.

Sadstar2016: для справки Задача - Переместить лист в первую позицию Исходные данные ----------------------------------- 1. Макрос Sheets("Лист3").Select Sheets("Лист3").Move Before:=Sheets(1) ----------------------------------- 2.Функция VBA Moves the sheet to another location in the workbook. expression.Move(Before, After) expression Required. An expression that returns an object in the Applies To list. Before Optional Variant. The sheet before which the moved sheet will be placed. You cannot specify Before if you specify After. After Optional Variant. The sheet after which the moved sheet will be placed. You cannot specify After if you specify Before. Remarks If you don't specify either Before or After, Microsoft Excel creates a new workbook that contains the moved sheet. Example This example moves Sheet1 after Sheet3 in the active workbook. Worksheets("Sheet1").Move after:=Worksheets("Sheet3") ----------------------------------- 3.Работающий вариант oBook:Sheets("Итого"):Move( oBook:Sheets(1) ) //поставить перед листом N1

Oskar_AAA: Добрый день, как вернуть активным окно программы, после запуска Excel (формирование сводного отчета. 60 и более листов) из отдельных Excel файлов...? начало формирования сводного отчета oExcel_S:=ToleAuto():New("Excel.Application") oExcel_S:Workbooks:Open(Day_Excel) oExcel_S:Set("DisplayAlerts",.F.) oExcel_S:Visible :=.T. oBook_S :=oExcel_S:ActiveWorkBook oAs_S :=oExcel_S:ActiveSheet() oSheet_S:=oBook_S :Sheets(1):Select() oSheet_S:=oBook_S :Sheets(1) oAs_S :Cells(1,15):Select() .... формирование листов из отдельных Excel файлов // переход к сводному отчету Hb_GtInfo(HB_GTI_CLIPBOARDDATA, "") oSheet_S:=oBook_S :Sheets(1):Select() oBook_S :=oExcel_S :ActiveWorkBook oAs_S :=oExcel_S :ActiveSheet() oSheet_S:=oBook_S :Sheets(1) oAs_S :Cells(1,5):Select() oSheet_S:Cells(1,5):Value=Dtoc(Date())+', '+Substr(Time(),1,5) oAs_S :Cells(1,7):Select() oSheet_S:Cells(1,7):Value=SecToTim(Seconds()-Start_Beg) oAs_S :Cells(1,1):Select() oBook_S :SaveAs(Upper(Day_Excel)) oExcel_S:Quit() oAs_S :=Nil oRange_S:=Nil oBook_S :=Nil oExcel_S:=Nil использовать oExcel_S:Visible :=.F. не вариант, надо что бы процесс формирования сводного Excel отчета был виден в фоновом окне, а окно программы стало активным... PS:xHarbour Compiler build 1.2.1 (SimpLex) (Rev. 6476)

Andrey: Oskar_AAA пишет: как вернуть активным окно программы, после запуска Excel Надо получить хендл своей программы и переключиться на неё. Используй несколько функций из МиниГуи: GETWINDOW() потом BRINGWINDOWTOTOP() #pragma BEGINDUMP #include <windows.h> #include <hbapi.h> #include <shlobj.h> #include "hbapi.h" #include "hbapiitm.h" #include "hbvm.h" // ---------------- взято из MiniGui ----------------------------- HB_FUNC( FINDWINDOWEX ) { hb_retnl( ( LONG ) FindWindowEx( ( HWND ) hb_parnl( 1 ), ( HWND ) hb_parnl( 2 ), ( LPCSTR ) hb_parc( 3 ), ( LPCSTR ) hb_parc( 4 ) ) ); } HB_FUNC( ISICONIC ) { hb_retl( IsIconic( (HWND) hb_parnl(1)) ); } HB_FUNC( SETFOREGROUNDWINDOW ) { SetForegroundWindow( ( HWND ) hb_parnl( 1 ) ); } // --------------------------------------------- HB_FUNC( ISEXERUNNING ) // ( cExeNameCaseSensitive ) --> lResult { HANDLE hMutex = CreateMutex( NULL, TRUE, (LPTSTR) hb_parc(1) ); hb_retl( GetLastError() == ERROR_ALREADY_EXISTS ); ReleaseMutex( hMutex ); } HB_FUNC( GETFOREGROUNDWINDOW ) { hb_retnl( (LONG) GetForegroundWindow() ); } HB_FUNC( BRINGWINDOWTOTOP ) { BringWindowToTop( ( HWND ) hb_parnl(1) ); } HB_FUNC ( FINDWINDOW ) { hb_retnl( ( LONG ) FindWindow( 0, hb_parc( 1 ) ) ); } HB_FUNC( MINIMIZE ) { ShowWindow( (HWND) hb_parnl(1), SW_MINIMIZE ); } HB_FUNC( MAXIMIZE ) { ShowWindow( (HWND) hb_parnl(1), SW_RESTORE ); ShowWindow( (HWND) hb_parnl(1), SW_MAXIMIZE ); } HB_FUNC( MAXIRESTORE ) { ShowWindow( (HWND) hb_parnl(1), SW_RESTORE ); } HB_FUNC( GETWINDOWTEXT ) { int iLen = SendMessage( (HWND) hb_parnl(1), WM_GETTEXTLENGTH, 0, 0 ) + 1; char *cText = ( char * ) hb_xgrab( iLen ); GetWindowText( (HWND) hb_parnl(1), (LPTSTR) cText, iLen ); hb_retc( cText ); hb_xfree( cText ); } HB_FUNC( GETWINDOW ) { hb_retnl( (LONG) GetWindow((HWND) hb_parnl(1), hb_parni(2)) ); } #pragma ENDDUMP Только вот как получить хендл своей программы в хХарборе пока не знаю...

Oskar_AAA: Тоже попробовал использовать HB_FUNC( MINIMIZE ) { ShowWindow( (HWND) hb_parnl(1), SW_MINIMIZE ); } HB_FUNC( MAXIMIZE ) { ShowWindow( (HWND) hb_parnl(1), SW_RESTORE ); ShowWindow( (HWND) hb_parnl(1), SW_MAXIMIZE ); } HB_FUNC( MAXIRESTORE ) { ShowWindow( (HWND) hb_parnl(1), SW_RESTORE ); } тестирую...

Andrey: Вот ещё посмотри, для хХарбора раньше делал: ************************************************************************* * Copyright : (c) 2008, Verchenko Andrey. E-mail: 30195@mail.ru * : Все права сохраняются. * Date : 11/11/2008 * Avtor : Верченко Андрей * Rem : Получение списка ХЕНДЛов окон и ИМЕН окон запущенных в системе * : только на xHarbour'e * : Отдельное СПАСИБО модераторам: Петру и Григорию * : http://clipper.borda.ru/?1-1-0-00000159-000-0-1-1226399294 ************************************************************************** #include "common.ch" #include "inkey.ch" FUNCTION MAIN() LOCAL aStart := {}, nI, aMenu:={}, aItems:={}, nSelect, cTemp LOCAL nSEL, cMess, aOpt cMess := "Выберите действие с этим процессом..." aOpt := {"Свернуть","Развернуть","Спрятать","Показать","Убить"} STRFILE("","Process.lst", .F.) aStart := GetWindowList() // Считать ХЕНДЛ окна и ИМЯ окна FOR nI:= 1 TO LEN(aStart) AADD( aMenu, { aStart[nI,1], HB_ANSITOOEM(aStart[nI,2]) } ) cTemp := STR(aStart[nI,1])+", "+HB_ANSITOOEM(aStart[nI,2]) AADD( aItems, cTemp ) STRFILE( cTemp+CHR(13)+CHR(10),"Process.lst",.T.) NEXT CLEAR SCREEN @ 1,7 SAY "Хендл окна Название окна" COLOR("11/0") DO WHILE LastKey() <> K_ESC nSelect := Achoice( 2, 5, MaxRow()-2, 75, aItems, .T. ) IF nSelect <> 0 // ВЫБОР ДЕЙСТВИЯ nSEL := Alert(cMess,aOpt) DO CASE CASE nSEL == 1 MINIMIZE( aStart[nSelect,1] ) Alert("Окно было свернуто") CASE nSEL == 2 // Display selected file MAXIMIZE( aStart[nSelect,1] ) Alert("Окно было развернуто на весь экран") CASE nSEL == 3 HIDE( aStart[nSelect,1]) Alert("Окно сделано невидимым") CASE nSEL == 4 SSHOW( aStart[nSelect,1]) Alert("Окно стало видимым") CASE nSEL == 5 KKILL( aStart[nSelect,1]) Alert("Окну отправлена команда на закрытие") ENDCASE KEYBOARD Chr(255) // sets Lastkey() to 255 Inkey() ENDIF ENDDO RETURN NIL #define GW_HWNDFIRST 0 #define GW_HWNDLAST 1 #define GW_HWNDNEXT 2 #define GW_HWNDPREV 3 #define GW_OWNER 4 #define GW_CHILD 5 function GetWindowList() LOCAL aWindows := {}, cTitle := "" LOCAL hWnd := GetWindow( GetForegroundWindow(), GW_HWNDFIRST ) WHILE hWnd != 0 // Loop through all the windows if !empty(cTitle := GetWindowText( hWnd )) AADD( aWindows, {hWnd, upper(cTitle)} ) endif hWnd := GetWindow( hWnd, GW_HWNDNEXT ) // Get the next window ENDDO return aWindows #pragma BEGINDUMP #include <windows.h> #include <hbapi.h> #include <shlobj.h> #define VM_CLOSE 16 HB_FUNC( ISEXERUNNING ) // ( cExeNameCaseSensitive ) --> lResult { HANDLE hMutex = CreateMutex( NULL, TRUE, (LPTSTR) hb_parc(1) ); hb_retl( GetLastError() == ERROR_ALREADY_EXISTS ); ReleaseMutex( hMutex ); } HB_FUNC( GETFOREGROUNDWINDOW ) { hb_retnl( (LONG) GetForegroundWindow() ); } HB_FUNC( MINIMIZE ) { ShowWindow( (HWND) hb_parnl(1), SW_MINIMIZE ); } HB_FUNC( MAXIMIZE ) { ShowWindow( (HWND) hb_parnl(1), SW_RESTORE ); } HB_FUNC( HIDE ) { ShowWindow( (HWND) hb_parnl(1), SW_HIDE ); } HB_FUNC( SSHOW ) { ShowWindow( (HWND) hb_parnl(1), SW_SHOW ); } HB_FUNC( KKILL ) { SendMessage( (HWND) hb_parnl(1), VM_CLOSE,0,0); //DestroyWindow( (HWND) hb_parnl(1), VM_CLOSE); } HB_FUNC( GETWINDOWTEXT ) { int iLen = SendMessage( (HWND) hb_parnl(1), WM_GETTEXTLENGTH, 0, 0 ) + 1; char *cText = ( char * ) hb_xgrab( iLen ); GetWindowText( (HWND) hb_parnl(1), (LPTSTR) cText, iLen ); hb_retc( cText ); hb_xfree( cText ); } HB_FUNC( GETWINDOW ) { hb_retnl( (LONG) GetWindow((HWND) hb_parnl(1), hb_parni(2)) ); } #pragma ENDDUMP

Dima: Oskar_AAA Попробуй где то в самом начале своей программы после любого вывода на экран получить хендл своего окна с помощью GETFOREGROUNDWINDOW (взять можно в Минигуи) А после запуска Excel используй ShowWindow + BringWindowToTop (взять можно в Минигуи)

Oskar_AAA: Dima можно выслать из Минигуи GETFOREGROUNDWINDOW и ShowWindow + BringWindowToTop я не работал в Минигуи... Спасибо...

Dima: Oskar_AAA [pre2] #pragma BEGINDUMP #include <windows.h> #include <hbapi.h> HB_FUNC (GETFOREGROUNDWINDOW) { HWND hWnd = GetForegroundWindow(); hb_retnl ((LONG) hWnd); } #pragma ENDDUMP [/pre2] [pre2] #pragma BEGINDUMP #include <windows.h> #include <hbapi.h> #include "hbapiitm.h" HB_FUNC( BRINGWINDOWTOTOP ) { BringWindowToTop( ( HWND ) hb_parnl( 1 ) ); } HB_FUNC( SHOWWINDOW ) { ShowWindow( ( HWND ) hb_parnl( 1 ), HB_ISNUM( 2 ) ? hb_parni( 2 ) : SW_SHOW ); } HB_FUNC( SETFOCUS ) { hb_retnl( ( LONG_PTR ) SetFocus( ( HWND ) hb_parnl( 1 ) ) ); } HB_FUNC( SETFOREGROUNDWINDOW ) { SetForegroundWindow( ( HWND ) hb_parnl( 1 ) ); } #pragma ENDDUMP [/pre2]

Oskar_AAA: Спасибо, начну тестировать...

Oskar_AAA: Dima вылетает по ошибке Warning W8065 Call to function 'HB_ISNUM' with no prototype in function HB_FUN_SHOWWINDOW вот фрагмент головного модуля... Procedure MAIN(Shifr) //INGAZ # Include 'Achoice.Ch' # Include 'Inkey.Ch' # Include 'Directry.Ch' # Include 'Setcurs.Ch' # Include 'Dbstruct.Ch' # Include 'Command.Ch' # Include 'Dbedit.Ch' # Include 'Excel.Ch' # Include 'Hbgtinfo.Ch' # Include 'Dbedit.Ch' Public Ctitle Ctitle:='INGAZ' C_Title=Ctitle+'.EXE' // SetConsoleTitle(cTitle) hWnd := FindWindow( cTitle ) DeleteCloseButton( hWnd ) #PRAGMA BEGINDUMP # include "Hbapi.h" # include "Windows.h" # include "Hbapiitm.h" HB_FUNC( SETCONSOLETITLE ) { hb_retl( SetConsoleTitle( hb_parc( 1 ) ) ) ; } HB_FUNC( FINDWINDOW ) { hb_retnl( (LONG)FindWindow( NULL, hb_parc( 1 ) ) ) ; } HB_FUNC( DELETECLOSEBUTTON ) { DeleteMenu(GetSystemMenu( (HWND)hb_parnl( 1 ), FALSE), SC_CLOSE, MF_BYCOMMAND ) ; DrawMenuBar( (HWND)hb_parnl( 1 ) ) ; } HB_FUNC_STATIC( SETFILEAPIS ) // OEM { SetFileApisToOEM(); } HB_FUNC (GETFOREGROUNDWINDOW) { HWND hWnd = GetForegroundWindow(); hb_retnl ((LONG) hWnd); } HB_FUNC( BRINGWINDOWTOTOP ) { BringWindowToTop( ( HWND ) hb_parnl( 1 ) ); } HB_FUNC( SHOWWINDOW ) { ShowWindow( ( HWND ) hb_parnl( 1 ), HB_ISNUM( 2 ) ? hb_parni( 2 ) : SW_SHOW ); } HB_FUNC( SETFOCUS ) { hb_retnl( ( LONG_PTR ) SetFocus( ( HWND ) hb_parnl( 1 ) ) ); } HB_FUNC( SETFOREGROUNDWINDOW ) { SetForegroundWindow( ( HWND ) hb_parnl( 1 ) ); } #pragma ENDDUMP // REQUEST HB_CODEPAGE_RU866 REQUEST DBFCDX,DBFFPT HB_SetCodePage( "RU866" ) RDDSetDefault('DBFCDX') SetMode(25,80)

Dima: Oskar_AAA пишет: вылетает по ошибке Warning W8065 Call to function 'HB_ISNUM' Нужно смотреть какой аналог этой функции в Xharbour , я "сижу" на Harbour

Pasha: ISNUM( 2 ) регистр существенен.

Oskar_AAA: Коллеги, функция SETCONSOLETITLE (удаление возможности закрыть программу по "крестику") работает не зависимо от регистра.. в HbApi.h нашел #define ISNUM( n ) ( hb_param( n, HB_IT_NUMERIC ) != NULL )

Dima: Oskar_AAA пишет: Коллеги, функция SETCONSOLETITLE (удаление возможности закрыть программу по "крестику") работает не зависимо от регистра.. Не вижу связи крестика и функции что рисует заголовок у окна. Или я вопрос не понял ?

Oskar_AAA: Pasha пишет: ISNUM( 2 ) регистр существенен.

Oskar_AAA: Добрый вечер, с Вашей помощью вот что получилось: В головной программе, после вывода меню на экран Handl_Win=GetForeGroundWindow() ?Handl_Win 5178634 далее обработка БД и создание Xls файлов (43 шт) создание из макета сводного отчета Xls с 42 листами oExcel_S:=ToleAuto():New("Excel.Application") oExcel_S:Workbooks:Open(Day_Excel) oExcel_S:Set("DisplayAlerts",.F.) oExcel_S:Visible :=.T. // ¢¨§ã «¨§ æ¨ï ᢮¤-®£® ®âç¥â  oBook_S :=oExcel_S:ActiveWorkBook oAs_S :=oExcel_S:ActiveSheet() oSheet_S:=oBook_S :Sheets(1):Select() oSheet_S:=oBook_S :Sheets(1) oAs_S :Cells(1,15):Select() oSheet_S:Cells(1,15):Value=Cdata // ¤ â  ®âç¥â  oSheet_S:Cells(1,18):Value=Bom(Cdata) // ¤ â  - ç «  ¬¥áïæ  oAs_S :Cells(1,1):Select() // ShowWindow(Handl_Win) BringWindowToTop(Handl_Win) SetFocus(Handl_Win) ?Handl_Win 5178634 wait перехода (активации) к программе из Excel не происходит... что сделано не так???

Andrey: Oskar_AAA пишет: перехода (активации) к программе из Excel не происходит... что сделано не так??? Найди хендл окна Excel и потом переключись на него ! Хенд у окна Excel получить просто - смотреть пример ExcelOle.prg .... выложил готовые примеры у Григория на сайте - http://hmgextended.com/applications.html [pre2] // окно таблицы Excel на передний план hWnd := oExcel:hWnd ShowWindow( hWnd, 6 ) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 INKEYGUI(100) ShowWindow( hWnd, 3 ) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 BringWindowToTop( hWnd ) [/pre2]

Oskar_AAA: Andrey окно Excel и так является активным, мне надо его сделать видимым но не активным, т.е пусть будет на экране в фоновом режиме... или если Хенд Excel просто получить, надо сделать окно таблицы на второй план как? Спасибо. Посмотрю ссылки Григория

Dima: Oskar_AAA пишет: ShowWindow(Handl_Win) Тут имеет значение 2 параметр если не ошибаюсь. Андрей уже показал. У Вас его нет совсем.

Oskar_AAA: поставил из из его модуля hWnd := oExcel_S:hWnd ShowWindow( hWnd, 6 ) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 окно Excel стало маленьким, но осталось на переднем плане, как его сделать на ВТОРОМ плане?

fil: Поменять Z-последовательность окна можно через SetWindowPos, а проще ShowWindow другого-какого окна вот Excel и уйдет в фон. Можно свое окно посадить на передний план

Oskar_AAA: FIL Как свое окно СНОВА посадить на Передний план (вычислил Хедлы по своей программе и Excel). но : в головном модуле: Askar_Win=GetForeGroundWindow() hWnd := oExcel_S:hWnd *ShowWindow(hWnd,6) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 ShowWindow(hWnd,3) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 // ShowWindow(Askar_Win,3) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 BringWindowToTop(Askar_Win) на передний план сове окно не возвращается..

fil: SetWindowPos(hWnd, -1, 0,0,0,0,3)

Dima: Oskar_AAA А если так [pre2] if isiconic(Askar_Win) SetForeGroundWindow(Askar_Win) endif ShowWindow(Askar_Win, 9) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 RESTORE=9 BringWindowToTop(Askar_Win) [/pre2] Задача под каким терминалом собрана ? Под GTWVT у меня такая связка работает.

Oskar_AAA: Dima попробуем, рахмат... программа xHarbour - консольный 25 х 80,

Oskar_AAA: Dima где взять функцию Isconic()? if isiconic(Askar_Win) ///

Andrey: Oskar_AAA пишет: где взять функцию Isconic()? Смотри в этой ветке Пост N: 5282 HB_FUNC( ISICONIC )

Oskar_AAA: ok

Dima: Oskar_AAA Наваял простой пример на Harbour , терминал STD. Запускаем пример и после куда то переключаемся. Через 10 секунд , окно примера появляется , но окно фокус ввода не получает , даже если и указать Setfocus(Askar_Win). Но если собрать под терминалом GTWVT , добавив REQUEST HB_GT_WVT_DEFAULT то все работает , как я выше и писал. PS Может Паша или Пётр чего подскажут [pre2] ? "Test" Askar_Win:=GETFOREGROUNDWINDOW() Inkey(10) if isiconic(Askar_Win) SetForeGroundWindow(Askar_Win) endif ShowWindow(Askar_Win, 9) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 RESTORE=9 BringWindowToTop(Askar_Win) wait ************** #pragma BEGINDUMP #include <windows.h> #include <hbapi.h> #include "hbapiitm.h" HB_FUNC (GETFOREGROUNDWINDOW) { HWND hWnd = GetForegroundWindow(); hb_retnl ((LONG) hWnd); } HB_FUNC( BRINGWINDOWTOTOP ) { BringWindowToTop( ( HWND ) hb_parnl( 1 ) ); } HB_FUNC( ISICONIC ) { hb_retl( IsIconic( ( HWND ) hb_parnl( 1 ) ) ); } HB_FUNC( SHOWWINDOW ) { ShowWindow( ( HWND ) hb_parnl( 1 ), HB_ISNUM( 2 ) ? hb_parni( 2 ) : SW_SHOW ); } HB_FUNC( SETFOCUS ) { hb_retnl( ( LONG_PTR ) SetFocus( ( HWND ) hb_parnl( 1 ) ) ); } HB_FUNC( SETFOREGROUNDWINDOW ) { SetForegroundWindow( ( HWND ) hb_parnl( 1 ) ); } #pragma ENDDUMP [/pre2]

Oskar_AAA: Dima программа xHarbour Compiler build 1.2.1 (SimpLex) (Rev. 6476). консольная (25 х 80) REQUEST HB_CODEPAGE_RU866 REQUEST DBFCDX,DBFFPT HB_SetCodePage( "RU866" ) RDDSetDefault('DBFCDX') SetMode(25,80) если REQUEST HB_GT_WVT REQUEST HB_GT_WVT_DEFAULT и подключаю GTWVT.lib при запуске программы выводится сообщение Unrecoverable error 10001 It's not a GUI programm переделывать под GUI - времени вообще нет... PS все функции Ваши & Andrey собрались и по ним ошибок при сборке программы нет. If Isiconic(Askar_Win) SetForeGroundWindow(Askar_Win) Endif ShowWindow(Askar_Win,9) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 RESTORE=9 BringWindowToTop(Askar_Win) set color to w/n ?hWnd,Askar_Win,Isiconic(Askar_Win) wait выдают числовые значения, Isiconic(Askar_Win)= .F.

Dima: Oskar_AAA К сожалению по Xharbour ни чего сказать не могу , давно слез с него на Harbour

Oskar_AAA: Коллеги, получилось в консольном xHarbour управлять окном и размером окна Excel с передачей фокуса на программу. Dima, Andrey и всем откликнувшемся - Рахмат # Include 'Achoice.Ch' # Include 'Command.Ch' # Include 'Dbedit.Ch' # Include 'Dbstruct.Ch' # Include 'Directry.Ch' # Include 'Excel.Ch' # Include 'Inkey.Ch' # Include 'Setcurs.Ch' # Include 'Hbgtinfo.Ch' // крестик на окне программы SetConsoleTitle(CTitle) hWnd:=FindWindow(CTitle) DeleteCloseButton(hWnd) // имена файлов в кириллице SetFileApis() // •Ґ-¤« ®Є®- Public Askar_Win1,Askar_Win2 Askar_Win1=GetForeGroundWindow() Askar_Win2=GetWindow() // REQUEST HB_CODEPAGE_RU866 REQUEST DBFCDX,DBFFPT HB_SetCodePage( "RU866" ) RDDSetDefault('DBFCDX') SetMode(25,80) обработка и так далее (создание временных Excel файлов....) создание сводного Excel отчета со многими листами из временных Excel файлов oExcel_S:=ToleAuto():New("Excel.Application") oExcel_S:Workbooks:Open(Day_Excel) oExcel_S:Set("DisplayAlerts",.F.) oExcel_S:Visible :=.T. // ўЁ§г «Ё§ жЁп бў®¤-®Ј® ®взҐв  oBook_S :=oExcel_S:ActiveWorkBook oAs_S :=oExcel_S:ActiveSheet() oSheet_S:=oBook_S :Sheets(1):Select() oSheet_S:=oBook_S :Sheets(1) oAs_S :Cells(1,15):Select() oSheet_S:Cells(1,15):Value=Cdata // ¤ в  ®взҐв  oSheet_S:Cells(1,18):Value=Bom(Cdata) // ¤ в  - з «  ¬Ґбпж  oAs_S :Cells(1,1):Select() // управление окнами hWnd := oExcel_S:hWnd ShowWindow(hWnd,3) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 RESTORE=9 If Askar_Win1>0 SetForeGroundWindow(Askar_Win1) Endif ShowWindow(Askar_Win1,9) //SW_MAXIMIZE=3 SW_NORMAL=1 SW_MINIMIZE=6 RESTORE=9 BringWindowToTop(Askar_Win1) // вывод программы на ПЕРЕДНИЙ план сборка листов отчета #PRAGMA BEGINDUMP # include "Hbapi.h" # include "Windows.h" # include "Hbapiitm.h" # include "Shlobj.h" HB_FUNC( SETCONSOLETITLE ) { hb_retl( SetConsoleTitle( hb_parc( 1 ) ) ) ; } HB_FUNC( FINDWINDOW ) { hb_retnl( (LONG)FindWindow( NULL, hb_parc( 1 ) ) ) ; } HB_FUNC( DELETECLOSEBUTTON ) { DeleteMenu(GetSystemMenu( (HWND)hb_parnl( 1 ), FALSE), SC_CLOSE, MF_BYCOMMAND ) ; DrawMenuBar( (HWND)hb_parnl( 1 ) ) ; } HB_FUNC( SETFILEAPIS ) // OEM { SetFileApisToOEM(); } HB_FUNC( ISICONIC ) { hb_retl( IsIconic( (HWND) hb_parnl(1)) ); } // ®ЇаҐ¤Ґ«Ґ-ЁҐ  ЄвЁў-®Ј® ®Є-  HB_FUNC (GETFOREGROUNDWINDOW) { HWND hWnd = GetForegroundWindow(); hb_retnl ((LONG) hWnd); } HB_FUNC( BRINGWINDOWTOTOP ) { BringWindowToTop( ( HWND ) hb_parnl( 1 ) ); } HB_FUNC( SHOWWINDOW ) { ShowWindow( ( HWND ) hb_parnl( 1 ), SW_SHOW ); } HB_FUNC( SETFOCUS ) { hb_retnl( ( LONG_PTR ) SetFocus( ( HWND ) hb_parnl( 1 ) ) ); } HB_FUNC( SETFOREGROUNDWINDOW ) { SetForegroundWindow( ( HWND ) hb_parnl( 1 ) ); } HB_FUNC( GETWINDOWTEXT ) { int iLen = SendMessage( (HWND) hb_parnl(1), WM_GETTEXTLENGTH, 0, 0 ) + 1; char *cText = ( char * ) hb_xgrab( iLen ); GetWindowText( (HWND) hb_parnl(1), (LPTSTR) cText, iLen ); hb_retc( cText ); hb_xfree( cText ); } HB_FUNC( GETWINDOW ) { hb_retnl( (LONG) GetWindow((HWND) hb_parnl(1), hb_parni(2)) ); } #PRAGMA ENDDUMP

Dima: Oskar_AAA пишет: и подключаю GTWVT.lib при запуске программы выводится сообщение Unrecoverable error 10001 It's not a GUI programm переделывать под GUI - времени вообще нет... GUI тут совсем не при чем.

Pasha: Здесь: https://support.microsoft.com/ru-ru/kb/124103 написано, как получить hWnd для консоли через вызов FindWindow так же есть оговорка: Полученный дескриптор HWND не обязательно подходит для всех операций дескриптор окна. Если немного модифицировать функции winapi, чтобы проанализировать возвращаемые значения: HB_FUNC( BRINGWINDOWTOTOP ) { hb_retnl( BringWindowToTop( ( HWND ) hb_parnl( 1 ) ) ); } HB_FUNC( SETFOREGROUNDWINDOW ) { hb_retnl( SetForegroundWindow( ( HWND ) hb_parnl( 1 ) ) ); } и сделать тест: Function TestWnd Local ch := hb_gtinfo(HB_GTI_WINTITLE) Local hWnd1 := FindWindow(ch) Local hWnd2 := FindWindow('Паук') ? SETFOREGROUNDWINDOW(hWnd2) ? BringWindowToTop(hWnd2) Inkey(2) ? SETFOREGROUNDWINDOW(hWnd1) ? BringWindowToTop(hWnd1) return nil Запустить игрушку паук, и этот тест. Результат: ? SETFOREGROUNDWINDOW(hWnd1) возвращает 0, то есть не работает Похоже, здесь срабатывает та самая оговорка.

Oskar_AAA: Спасибо, за советы и участие. Обошелся проверкой на значение GetForeGroundWindow() >0 . Получилось то, что хотел в консоли

fokinal21: Надо очистить таблицу от пустых строк. Что-то из Harbour никак не получается... Может кто подскажет? Спасибо

Dima: fokinal21 пишет: Надо очистить таблицу от пустых строк Вопрос не очень понятен.

Dima: fokinal21 Может имелось в виду скрыть диапазон строк ?

fokinal21: Есть таблица в Excel, надо удалить пустые строки В моем частном случае дело упрощается тем, что их можно определить по пустым ячейкам первого столбца В vba это решается просто и понятно: Sub RowDel() LastRow = ActiveSheet.UsedRange.Row - 1 + ActiveSheet.UsedRange.Rows.Count Application.ScreenUpdating = False For r = LastRow To 1 Step -1 If Application.Rows(r).Columns(1).Value = "" Then Rows(r).Delete Next r End Sub Попытался перевести все это в Harbour и вот что получилось : Function RowDel() oExcel := CreateObject( "Excel.Application" ) oExcel:Workbooks:Open(Getfile()) oList := oExcel:Get( "ActiveSheet" ) oExcel:Visible("True") LastRow:= oList:UsedRange:Row-1 + oList:UsedRange:Rows:Count For r = LastRow To 1 Step -1 If oExcel:Rows(r):Columns(1):Value <>"" oExcel:Rows(r):Delete() endif Next r return при этом, если в vba прога срабатывает при Value = "", что логически верно, то в Harbour все работает при Value <>"" что совсем мне непонятно Это проверено на простой тестовой таблице - просто заполнил в первом столбце несколько ячеек не подряд Кроме этого vba спокойно глотает наличие чисел в части ячеек, Harbour падает в ошибку.

Петр: За такой перевод переводчик от технического редактора по рукам может получить Ближе к теме: вспоминайте, для чего предназначена функция Empty в hb, и countA в vba, а также посмотрите пример от MVP Dennis Wallentin в топике Range.Row Property (Excel) Sub Delete_Empty_Rows() 'This example deletes the empty rows from a selected range.

fokinal21: Петр пишет: вспоминайте, для чего предназначена функция Empty Спасибо! С Empty действительно все хорошо, но все же был интерес перевода готового примера в Harbour. Переведенный пример вполне рабочий (при текстовых заполнениях ячеек), но так и непонятно почему в Harbour все срабатывает при oExcel:Rows(r):Columns(1):Value <>"", может разъясните где логика порылась... А то как-то неспокойно

Петр: fokinal21 пишет: но все же был интерес перевода готового примера в Harbour Ну так переводите, только учтите, что при переводе Шекспира на русский используются правила русского языка. А при переводе этого примера на Harbour правильно было бы учитывать особенности vba, Excell и Harbour, а не только . на : поменять. [pre2]procedure main ? "" = "" ? "" = NIL ? "" <> "" ? "" <> NIL ? "" = 0[/pre2]

Oskar_AAA: Добрый день, коллеги Имеется файл с иерархической структурой строк, как определить уровень иерархии по строке. Пробовал такое: RowLevel=oSheet:Outline:ShowLevels RowLevels RowLevel=oAs:Row(Ni):Outline:RowLevels

Oskar_AAA: Решил: RowLevel=oSheet:Rows(Ni):OutlineLevel

Softlog86: Читаем / пишем .XLSX файлы из HARBOUR без использования EXCELL ! У меня всё получилось собрать . Примем на вооружение : https://github.com/FTrautwein/hblibxlsxwriter

fokinal21: Всем добрый вечер! Кусок кода: oExcel:=CreateObject( "Excel.Application" ) ? oExcel:hWnd oExcel:Quit() ? oExcel:hWnd В результате выводятся одинаковые значения. Почему, если Excel закрыт? Тоже самое происходит, если открыть файл и закрыть его вручную вместо Quit

Haz: fokinal21 пишет: Почему Потому что хендл окна присваиваивается при создании объекта и нет необходимости его актуализировать во время жизни объекта, т. к. это уже забота программиста. Еcли нужно что то с чемто сравнить, то нужно и проверить живо ли еще окно с таки хендлом

fokinal21: Haz пишет: Потому что хендл окна присваиваивается при создании объекта и нет необходимости его актуализировать во время жизни объекта Получается, что после Quit объект еще не умер? Если закрыть окно "крестиком" - тот же результат. Haz пишет: проверить живо ли еще окно с таки хендлом А как проверить? Этот результат появился после танцев вокруг поиска способа именно такой проверки.

Dima: fokinal21 пишет: oExcel:Quit() я после этого делаю так oWorkBook:=nil oSheet:=nil oExcel:=nil

Haz: fokinal21 пишет: А как проверить? Ну есть к примеру enumwindows которая возвращает список активных окон в системе. Возможно есть способ проще, типа похендлу получить статус окна... именно живо ли оно

Петр: Haz пишет: Возможно есть способ проще, типа похендлу получить статус окна Валидность хэндла обычно проверяют с использованием WinAPI функции IsWindow() В MiniGUI функция-враппер носит название IsWindowHandle(). if IsWindowHandle( oExcel:hWnd ) ...

fokinal21: oExcel :=CreateObject( "Excel.Application" ) hWnd:=oExcel:hWnd ? hWnd ? IsWindowHandle(hWnd) // Результаты: 462230 и .T. oExcel:Quit() ? hWnd ? IsWindowHandle(hWnd) // Результаты: 462230 и .T. *По рекомендации Dima oExcel:=nil ? hWnd ? IsWindowHandle(hWnd) // Результаты: 462230 и .T. // Итог: oExcel опять живее всех живых, несмотря на oExcel:Quit() и oExcel:=nil

Dima: fokinal21 пишет: *По рекомендации Dima oExcel:=nil ? hWnd ? IsWindowHandle(hWnd) // Результаты: 462230 и .T. // Итог: oExcel опять живее всех живых, несмотря на oExcel:Quit() и oExcel:=nil Ну тогда нужно так oExcel:Quit() oExcel:=nil ? hWnd:=oExcel:hWnd ? IsWindowHandle(hWnd) // Итог: результат в студию

Sergy: Dima пишет: oExcel:Quit() oExcel:=nil ? hWnd:=oExcel:hWnd ? IsWindowHandle(hWnd) // Итог: результат в студию Можно даже не компилировать - результатом будет ошибка времени исполнения, тк у переменной типа NIL не может быть свойства :hWnd А ноги у этой проблемы вот отсюда растут: http://clipper.borda.ru/?1-4-0-00001096-000-0-0-1440920410 Вот тут тоже обсуждали: http://clipper.borda.ru/?1-4-0-00000591-000-0-0-1317808661 Вот решение: http://clipper.borda.ru/?1-4-0-00000876-000-0-0-1373554002 [pre2] func Start_Excel() Local Res:=.f. #ifndef __XHARBOUR__ #xcommand TRY => BEGIN SEQUENCE WITH {|e| Break( e )} #xcommand CATCH [<!oErr!>] => RECOVER [USING <oErr>] <-oErr-> #endif TRY oExcel := GetActiveObject( "Excel.Application" ) oExcel:DisplayAlerts:=.f. Res:=.t. CATCH Res:=.f. TRY oExcel := CreateObject( "Excel.Application" ) Res:=.t. CATCH Res:=.f. END END Return Res [/pre2] Т.е. если процесс уже есть в памяти - использовать его, а не создавать новый.

fokinal21: В общем понятно, что процесс Excel закрывается только после закрытия вызвавшей его программы, как ни крути Quit - ами и nil - ами. И это значит, что попытки выяснить с помощью хендла закрыл юзер окно с табличкой или нет обречены на провал, а это и надо было мне сделать. Может кто проведет другим путем?

Dima: fokinal21 пишет: это значит, что попытки выяснить с помощью хендла закрыл юзер окно с табличкой или нет обречены на провал А зачем это контролировать ? Выбросил форму в Excel а дальше юзер что хочет с ней то и делает. У себя делаю примерно так: oExcel:DisplayAlerts:=.t. oExcel:Visible := .t. oSheet:Cells( 1, 1 ):select() //oSheet:Protect( "blabla" ) Showexcel(oExcel)

Haz: fokinal21 пишет: Может кто проведет другим путем? Да легко Суть в том что любое окно порождено конкретным процессом. Отслеживать хендл окна дело бесперспективное т. к. Винда использует повторное пернназначение (хендл закрытого окна может пллучтьб вновь созданное) Поэтому имеет смысл привязыватьсяименно к процессу еоторый это окно родил. И задача сводится к тому что бы определить жив ли сам процесс. Как определить? По алгоритму 1.зная окно можно найти процесс который его создал 2.зная процесс получить программу которая в нем выполняетя 3.и если это тот процесс и та программа то юзер ее еще не убил Ps в харбуре есть инструмент чтоб этот алгоритм проверить Будут вопросы пиши. На чтото я смогу ответить на что-то коллеги помогут

fokinal21: Haz пишет: Как определить? По алгоритму 1.зная окно можно найти процесс который его создал 2.зная процесс получить программу которая в нем выполняетя 3.и если это тот процесс и та программа то юзер ее еще не убил Пока на все один большой вопрос ? Чтобы превратить его в несколько маленьких ,стремящихся к 0, можно чуть подробнее и небольшой пример, можно ссылку, если таковой уже есть.

Петр: fokinal21 пишет: Пока на все один большой вопрос ? Чтобы превратить его в несколько маленьких ,стремящихся к 0, можно чуть подробнее и небольшой пример, можно ссылку, если таковой уже есть. Зачем это все прикладному программисту? fokinal21 пишет: В общем понятно, что процесс Excel закрывается только после закрытия вызвавшей его программы, как ни крути Quit - ами и nil - ами. И это значит, что попытки выяснить с помощью хендла закрыл юзер окно с табличкой или нет обречены на провал, а это и надо было мне сделать. Может кто проведет другим путем? oExсel:hWnd хранит хэндл главного окна oExсel (с классом 'XLMAIN'), как вы его собираетесь использовать для определения окна с табличкой, это еще вопрос. oExсel также имеет коллекцию Windows - "that represents all the windows in all the workbooks", вот я б с ней пробовал работать в вашей ситуации.

Haz: fokinal21 пишет: Пока на все один большой вопрос ? Чтобы превратить его в несколько маленьких ,стремящихся к 0, можно чуть подробнее и небольшой пример, можно ссылку, если таковой уже есть. Вот тот самый небольшой пример. Показывает окна их класс и заголовки. В том числе если есть открытая книга в Excel то ее и покажет в списке [pre2] #include "common.ch" #include "i_winuser.ch" #define WM_GETTEXT 0x000D #define WM_SETTEXT 0x000C #define WM_GETTEXTLENGTH 0x000E Func main() local hWnd := 0 local aWin := {} local aChild := {} local hChildWindow := 0 local i := 0 local j := 0 local nLen := 0 local nLenCh := 0 REQUEST HB_LANG_RU866 HB_LANGSELECT("RU866") REQUEST HB_CODEPAGE_RU1251 hb_cdpSelect( "RU1251" ) aWin := EnumWindows() nLen := len( aWin ) for i := 1 to nLen aChild := EnumChild( aWin[ i ] ) nLenCh := LEN( aChild ) for j := 1 TO nLenCh ? aChild[j][2], aChild[ j ][3] end end return NIL Func EnumChild( hWin ) local aChild := {} EnumChildWindows( hWin, { |hChild, nLParam | AADD( aChild, { hChild, GetClassName( hChild ), GetChildWindowText(hChild) } ) , .T. }, 0 ) return aChild FUNCTION GetChildWindowText(hWnd ) LOCAL nLen, cText nLen := SendMessage(hWnd, WM_GETTEXTLENGTH, 0, 0) + 1 cText := Space( nLen) nLen := SendMessageString(hWnd, WM_GETTEXT, nLen, @cText) RETURN substr(cText,1,nLen) ********************************************************************************************************************************************** * ********************************************************************************************************************************************** #pragma BEGINDUMP #include <windows.h> #include "hbapi.h" #include "hbapiitm.h" #include <hbapi.h> #include <hbapiitm.h> #include <windows.h> void hb_evalBlock( PHB_ITEM pCodeBlock, ... ); static PHB_ITEM pCodeBlock = NULL; BOOL CALLBACK static EnumChildProc( HWND hWnd, LPARAM lParam ) { PHB_ITEM pHWnd = hb_itemPutNL( NULL, ( LONG ) hWnd ); PHB_ITEM pParam = hb_itemPutNL( NULL, ( LONG ) lParam ); if( pCodeBlock ) hb_evalBlock( pCodeBlock, pHWnd, pParam, 0 ); hb_itemRelease( pHWnd ); hb_itemRelease( pParam ); return hb_parl( -1 ); } HB_FUNC( ENUMCHILDWINDOWS ) { HWND hWnd = ( HWND ) hb_parnl( 1 ); LPARAM lParam = ( LPARAM ) hb_parnl( 3 ); pCodeBlock = hb_param( 2, HB_IT_BLOCK ); hb_retl( EnumChildWindows( hWnd, EnumChildProc, lParam ) ); pCodeBlock = NULL; } BOOL CALLBACK static EnumWinProc( HWND hWnd, LPARAM lParam ) { PHB_ITEM pHWnd = hb_itemPutNL( NULL, ( LONG ) hWnd ); PHB_ITEM pParam = hb_itemPutNL( NULL, ( LONG ) lParam ); if( pCodeBlock ) hb_evalBlock( pCodeBlock, pHWnd, pParam, 0 ); hb_itemRelease( pHWnd ); hb_itemRelease( pParam ); return TRUE; } static PHB_ITEM pArray; #if defined( __BORLANDC__ ) #pragma argsused #endif BOOL CALLBACK EnumWindowsProc( HWND hWnd, LPARAM lParam ) { PHB_ITEM pHWnd = hb_itemPutNL( NULL, ( LONG ) hWnd ); #if defined( __MINGW32__ ) UNREFERENCED_PARAMETER( lParam ); #endif hb_arrayAddForward( pArray, pHWnd ); hb_itemRelease( pHWnd ); return TRUE; } HB_FUNC ( ENUMWINDOWS ) { pArray = hb_itemArrayNew( 0 ); EnumWindows( ( WNDENUMPROC ) EnumWindowsProc, ( LPARAM ) 0 ); hb_itemReturnRelease( pArray ); pArray = NULL; } BOOL CALLBACK EnumThreadWndProc( HWND hWnd, LPARAM lParam ) { PHB_ITEM pHWnd = hb_itemPutNL( NULL, ( LONG ) hWnd ); #if defined( __MINGW32__ ) UNREFERENCED_PARAMETER( lParam ); #endif hb_arrayAddForward( pArray, pHWnd ); hb_itemRelease( pHWnd ); return TRUE; } HB_FUNC ( GETCLASSNAME ) { HWND hWnd = (HWND) hb_parnl( 1 ); TCHAR ClassName[ 1024 ]; GetClassName( hWnd, ClassName, sizeof (ClassName) / sizeof (TCHAR) ); hb_retc( ClassName ); } HB_FUNC( GETWINDOWTEXT ) { HWND hWnd = ( HWND ) hb_parnl( 1 ); int iLen = GetWindowTextLength( hWnd ); char * cText = ( char * ) hb_xgrab( iLen + 1 ); int iRet = GetWindowText( hWnd, ( LPSTR ) cText, iLen + 1 ); hb_retclen( cText, iRet ); hb_xfree( cText ); } HB_FUNC( SENDMESSAGE ) { hb_retnl( ( LONG ) SendMessage( ( HWND ) hb_parnl( 1 ), ( UINT ) hb_parni( 2 ), ( WPARAM ) hb_parnl( 3 ), ( LPARAM ) hb_parnl( 4 ) ) ); } HB_FUNC( SENDMESSAGESTRING ) { hb_retnl( ( LONG ) SendMessage( ( HWND ) hb_parnl( 1 ), ( UINT ) hb_parni( 2 ), ( WPARAM ) hb_parnl( 3 ), ( LPARAM ) ( LPSTR ) hb_parc( 4 ) ) ); } HB_FUNC ( POSTMESSAGE ) { hb_retl( (BOOL) PostMessage ( (HWND) hb_parnl (1), (UINT) hb_parni (2), (WPARAM) hb_parnl (3), (LPARAM) hb_parnl (4) ) ); } #pragma ENDDUMP [/pre2]

fokinal21: Всем спасибо за помощь и консультации! Haz пишет: Вот тот самый небольшой пример Буду, по возможности, разбираться с примером...

Dima: fokinal21 пишет: Буду, по возможности, разбираться с примером... Пример по ходу отображается не верно , там где есть [ i ] только без пробелов внутри скобок

SergKis: Dima пишет Пример по ходу отображается не верно тут [pre2] for i := 1 to nLen aChild := EnumChild( aWin[ i ] ) nLenCh := LEN( aChild ) for j := 1 TO nLenCh ? aChild[j][2], aChild[j][3] end end[/pre2]

Haz: SergKis пишет: тут Дима , Сергей , спасибо . Подправил [ и ]

Петр: [pre2] REQUEST HB_LANG_RU866 REQUEST HB_CODEPAGE_RU1251 procedure Main( p, m ) local oExcel, oWorkBook, oWindows local nI, nCount, w hb_LangSelect( "RU866" ) hb_cdpSelect( "RU1251" ) hb_default( @p, "/" ) hb_default( @m, "/m" ) if hb_LeftEqI( p, "/g" ) .or. hb_LeftEqI( p, "-g" ) oExcel := win_oleGetActiveObject( "Excel.Application" ) elseif hb_LeftEqI( p, "/c" ) .or. hb_LeftEqI( p, "-c" ) oExcel := win_oleCreateObject( "Excel.Application" ) else ? Upper( __FILE__ ), '[/G|/C] [/M]' ? ' /C - Create new Excel object' ? ' /G - Get existing object' ? ' /M - Merge instances [by default]' ? '' endif if oExcel != NIL IF hb_LeftEqI( m, "/m" ) .or. hb_LeftEqI( m, "-m" ) oExcel:MergeInstances := .T. else oExcel:MergeInstances := .F. endif ? oExcel:hwnd ? '---------' oWindows := oExcel:Windows() oWorkBook := oExcel:WorkBooks:Add() nCount := oWindows:Count // Note that the active window is always Windows[1] oWindows[1]:Caption := "xl#win#" + hb_NtoS( nCount ) for each w in oWindows ? w:caption ? w:hwnd next oExcel:Visible := .T. //oExcel:Quit() else ? "Error: MS Excel not available. [" + win_oleErrorText() + "]" endif return [/pre2] Программа консольная. Компилировать как-то так hbmk2 myexcel.prg -lhbwin Запускать myexcel /c /m myexcel /g myexcel /g myexcel /g Рекомендую посмотреть, проанализировать и сделать выводы Интересно будет посмотреть на результат для разных версий Excel P.S. Excel 2016 работает чудненько.

Dima: Петр пишет: P.S. Excel 2016 работает чудненько. На 2003 падает на oExcel:MergeInstances и закоментил пока , пересобрал , запустил с ключом /C и упал в цикле на ? w:hwnd

Петр: Dima пишет: На 2003 падает на oExcel:MergeInstances Настоящий Эксель начинается с 2013 Dima пишет: упал в цикле на ? w:hwnd Припоминаю, что где-то мы уже это обсуждали, у Ворда свойство hwnd есть, у Экселя нет. В 2007(?) вроде уже есть.

Dima: Петр пишет: Настоящий Эксель начинается с 2013 Кажется в примере не хватает проверки перед его запуском на версию офиса , впрочем это уже обсуждали в одной из тем , так что кому надо тот сам и допилит. PS У многих еще стоит XP и далеко не SP3 , так что заюзать могут офис только ниже 2010

Петр: Dima пишет: Кажется в примере не хватает проверки перед его запуском на версию офиса Можно добавить в любом удобном месте ? oExcel:version И танцевать от результата Excel 2003 - 11.0 Excel 2007 - 12.0 Excel 2010 - 14.0 Excel 2013 - 15.0 Excel 2016 - 16.0

fil: Из своей проги открываю файл Excel. В этом файле есть кнопка которая активирует макрос. Макрос должен посылать сообщение - PostMessage(чего нибудь) моей проге и закрывть Excel. Не писал ли кто похожее ?

Петр: fil пишет: Не писал ли кто похожее ? Не писал, но не вижу на каком этапе могут возникнуть трудности: нажать кнопку (выполнить макрос), послать сообщение, закрыть Excel? Добавляйте описание WinAPI функций, что-то типа Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long и вперед. UPD: наверное вам пригодится RegisterWindowMessage.

fil: Не писал, но не вижу на каком этапе могут возникнуть трудности Да ни на каком, написал уже. Думал, вдруг кто халяву подкинет

Петр: fil пишет: Думал, вдруг кто халяву подкинет

fil: Можно ли программно подгрузить в книгу макрос из внешнего*.bas файла ?

Dima: Заполняю ячейку следующим значением hb_dtoc(Tmp123->data_z,"DD.MM.YYYY") NumberFormat для нее поставил "@" , вместо даты получил цифры. Глянул как в макросе делает Excel для даты , NumberFormat там "m/d/yyyy" , тоже вставил в проге но после этого оля упала. Какой вид NumberFormat нужно поставить что бы и оля не упала и дата корректно отобразилась ?

Петр: Dima пишет: Заполняю ячейку следующим значением hb_dtoc(Tmp123->data_z,"DD.MM.YYYY") Попробуйте заполнять так :Value := Date() :Value := hb_DateTime() :Value := Tmp123->data_z

Dima: Петр Дело в том что есть универсальная функция (моя) , обрабатывает DBF таблицу и кидает ее в EXCEL. Данные таблицы заполняю не по ячейкам а по строкам. То есть Value я присваиваю массив (в данном случае) вида {"17.06.2017","ИВАНОВ",45123.10} Если после присвоения (или до) не делать NumberFormat , то все ровно. Но понадобилось в 3 -й колонке число бить по разрядам что бы получить 45 123.10 , если этого не сделать получаю 45123.1 Поэтому решил диапазону (RANGE) передать массив вида {"@","@","# ##0"+GET_SDECIMAL()+"00"} через NumberFormat , все сработало за исключением вывода строки в которой дата. Подмена "@" на "m/d/yyyy" приводит к падению оли. Сделал пока временное решение но пришлось отказаться от заполнения диапазона в NumberFormat и сделал по ячейкам в цикле , скорость немного конечно упадет. Массив теперь выглядит так {NIL,"@","# ##0"+GET_SDECIMAL()+"00"} а в цикле проверка стоит , если не NIL то работаем с NumberFormat

Петр: Фрагмент кода oAS:Range( "A1:C1" ):Value := {"17.06.2017","ИВАНОВ",45123.10} oAS:Range( "A1:C1" ):NumberFormat := {"mm/dd/yyyy","@","# ##0,00"} oAS:Range( "A1:C1" ):Select() в Excell 2016 не приводит к падению Можно попробовать использовать (до или после) oAS:Columns( 3 ):NumberFormat.. или oAS:Range( "С3:C100" ):NumberFormat.. UPD. oAS:Range( "A1:C1" ):Value := {Date(),"ИВАНОВ",45123.10} - тоже работает как просили..

Dima: Петр пишет: в Excell 2016 не приводит к падению Возможно , у меня Excel 2000 У юзверей стоит , поэтому и у себя держу такую версию.

Oskar_AAA: Добрый день, формирую DBF файл и выводе в Excel использую NaumberFormat только где надо разделить разряды, убрать 0, перенос текста - пока все ОК (Excel 2010 - 2016)

Pasha: Как вариант: перед заполнением таблицы по строкам можно установить NumberFormat для тех столбцов, для которых это надо, т.е: oSheet:Columns( nCol1 ):NumberFormat := cFormat1 .. oSheet:Columns( nColN ):NumberFormat := cFormatN а затем сделать цикл по строкам с их заполнением Если есть шапка таблицы, то после форматирования всего столбца NumberFormat для шапки можно очистить, или установить другой: oSheet:Rows('1'+':'+AllTrim(Str(nRow))):NumberFormat := ... С точки зрения оптимизации так будет лучше всего, т.к. число вызовов NumberFormat будет минимально.

Dima: Pasha пишет: Как вариант: перед заполнением таблицы по строкам можно установить NumberFormat для тех столбцов, для которых это надо, т.е:

Pasha: Как уже отмечалось, харбор не поддерживает создание двумерных массивов Variant, и из-за этого в Excel не получается присвоить значение диапазону ячеек, состоящему из нескольких строк. Приходится присваивать значение построчно, что намного медленнее. Или копировать диапазон через буфер обмена. Это быстро, но сносит форматирование, что тоже не всегда приемлемо. Написал функцию, которая позволяет это делать. Ссылка на функцию с примером: http://my-files.ru/n4n4id

Dima: Pasha пишет: Написал функцию, которая позволяет это делать. Гениально , работает однако Спасибо !

Alex_Cher: Dima пишет: Гениально , работает однако у меня нет ... http://shot.qip.ru/00U6oZ-3JqTa71XL/ чего не хватает ?

Петр: Alex_Cher пишет: чего не хватает ? hbwin включена в проект?

Dima: Alex_Cher пишет: чего не хватает ? HBWIN

Alex_Cher: ... дальше больше http://shot.qip.ru/00U6oZ-6JqTa71XM/ надо было с С ++ начинать ...

Петр: Alex_Cher пишет: ... дальше больше Больше чего? В MiniGUI (последней версии) правите файл сборки call ..\..\..\batch\compile.bat _set2a /L hbwin %1 %2 %3 %4 %5 %6 %7 %8 %9 и спокойно компилируете.

Pasha: По поводу этого кода. Оригинальный фрагмент там совсем небольшой: создание двумерного массива, все остальное пришлось копировать из сырцов hbwin и xharbour, так как нужные функции там объявлены как static, и их не вызовешь. Как раз месяц назад в harbour dev list было обсуждение этого вопроса, и есть надежда, что поддержка таких массивов будет добавлена в hbwin. Тогда эта функция станет не нужна. Сейчас ее можно использовать для решения вполне конкретной и ограниченной задачи. Это что-то вроде заплатки.

Pasha: Pasha пишет: и есть надежда, что поддержка таких массивов будет добавлена в hbwin. Тогда эта функция станет не нужна. Ну вот, все вопросы в dev list утрясены, и поддержка многомерных массивов Variant добавлена в Harbour. Пример для заполнения диапазона в Excel: // файл из contrib\hbwin #include "hbole.ch" local aSet[nRows, nColumns] // далее надо заполнить двумерный массив со значениями ячеек // и вызвать oRange:Value := __oleVariantNew( WIN_VT_VARIANT, aSet, nRows, nColunms )

Dima: Pasha пишет: Ну вот, все вопросы в dev list утрясены, и поддержка многомерных массивов Variant добавлена в Harbour. Спасибо.

Vlad04: http://xlslib.sourceforge.net/index.php What is xlsLib? xlsLib is a multiplatform, a C/C++ library for dynamically generating Excel(TM) files (*.xls format). It allows the generation of these files directly without the need of other assistive software. xlsLib can be used: as a statically linked library. xlsLib can easily be integrated in any C/C++ project. As a dynamically linked library. The classic shared object scheme can be followed for using xlsLib. Последние обновления , кажется 14 годом.

Vlad04: Петр Может быть Вы обратили свое внимание на эту библиотеку. Цель - возможность работы с ней в Харбор/ MiniGui

Петр: Vlad04 пишет: Может быть Вы обратили свое внимание на эту библиотеку. Цель - возможность работы с ней в Харбор/ MiniGui Честно говоря, я не вижу в этом никакого профита. Активное продвижение формата xls завершилось в 2003 году - 14 лет назад. К тому же, несмотря на заявления, xlsLib типичная C++ библиотека. Использование с harbour (C) возможно, но это довольно сомнительное удовольствие. В MiniGUI есть пример для работы с libxlsxwriter.dll (формат xlsx).

Vlad04: Петр Ок, формат не критичен. К сожалению libxlsxwriter.dll имеет ряд ограничений - она не может читать или изменять существующие файлы! И , наверно, обязательно д.быть установлен Excel

Петр: Vlad04 пишет: К сожалению libxlsxwriter.dll имеет ряд ограничений - она не может читать или изменять существующие файлы! То же самое можна сказать о xlsLib Vlad04 пишет: И , наверно, обязательно д.быть установлен ExcelНет

Панченко: Петр пишет: В MiniGUI есть пример для работы с libxlsxwriter.dll (формат xlsx). Где лежит? Что-то не нахожу...

Dima: Панченко пишет: Где лежит? Что-то не нахожу... C:\MiniGUI\SAMPLES\Advanced\HbXlsxWriter\

Панченко: Dima Спасибо. Перешел на версию 17.06. Действительно, пример там и лежит :))

Панченко: Pasha пишет: все вопросы в dev list утрясены, и поддержка многомерных массивов Variant добавлена в Harbour. ... oRange:Value := __oleVariantNew( WIN_VT_VARIANT, aSet, nRows, nColunms ) Логичным был бы второй шаг - такое же быстрое заполнение массива значениями oRange:Value. Этот вопрос не поднимается?

Pasha: И до этих правок можно было считать в массив значение Range для диапазона ячеек. Только массив получался с перевернутыми размерностями: сначала столбец, потом строка. Теперь же в массив считываются значения диапазона как положено: [ <строка>, <столбец> ] Никаких дополнительных функций вызывать не надо, просто вызвать: aValues := oRange:Value

Панченко: to Pasha Спасибо.

Andrey: Pasha пишет: Как уже отмечалось, харбор не поддерживает создание двумерных массивов Variant, и из-за этого в Excel не получается присвоить значение диапазону ячеек, состоящему из нескольких строк. Приходится присваивать значение построчно, что намного медленнее. Или копировать диапазон через буфер обмена. Это быстро, но сносит форматирование, что тоже не всегда приемлемо. Написал функцию, которая позволяет это делать. Ссылка на функцию с примером: http://my-files.ru/n4n4id Файл удалён. Можно его выложить заново ?

Dima: Andrey пишет: Файл удалён. Можно его выложить заново ? https://cloud.mail.ru/public/22h1/4N2PZfRNW

Andrey: Спасибо !

Haz: Так оно Пашиными стараниями уже давно в дистрибутиве харбура. Я пользуюсь без всяких дополнительных функций. Все родное, харбуровское. Или речь не о том?

Andrey: Haz пишет: Я пользуюсь без всяких дополнительных функций. Все родное, харбуровское. Или речь не о том? А есть пример небольшой, демонстрирующий как этим пользоваться ?

PSP: Andrey пишет: А есть пример небольшой, демонстрирующий как этим пользоваться ? В файле по ссылке и есть пример.

Andrey: Haz пишет: Я пользуюсь без всяких дополнительных функций. Все родное, харбуровское. Или речь не о том? Да я не понял тоже. В примере разве - всё родное, харбуровское ?

Dima: Andrey пишет: А есть пример небольшой, демонстрирующий как этим пользоваться ? Пост N: 3573 в этой теме

fil: Есть переменная содержащая RTF структуру. Как вставить эту переменную в ячейку Excel не как текст, а как RTF ?

fil: Всем, привет ! Как можно программно войти в ячейку. Т.е. как если дважды кликнуть на ячейке и войти в режим редактирования. (макрос делал)

Dima: fil пишет: программно войти в ячейку Может это ?

fil: Только этот метод будет работать ежели Excel уже визуализирован. А так вроде подходит :SetKeys({"F2"}) :Paste() :SetKeys({"RETURN"}) А то ежели сделать paste не входя в ячейку, текст из клипборда распределится по строкам. В общем вся фигня из за того, что мне в ячейку Excel надо положить форматный текст, а в value ячейки можно положить только текст без формата. Остается paste

Andrey: Всем привет ! Переношу проект из HBOLE.LIB -> HBWIN.LIB Создаю экселовский файл из массива: [pre2]// дата , л/счёт , код , .... aDim := { DATE(), "901010"+HB_NtoS(10+nLine), "001", .... }[/pre2] В HBOLE.LIB использовал: [pre2] IF cType == "D" oSheet:Cells( nLine, nI ):SET( "NumberFormat", "@" ) [/pre2] Получалось так: При использовании HBWIN.LIB переделал код: [pre2] IF cType == "D" oSheet:Cells( nLine, nI ):NumberFormat := '@' // текстовая ячейка[/pre2] И так получается: Как для HBWIN.LIB сделать шаблон даты 99.99.9999 ?

Dima: Andrey пишет: Как для HBWIN.LIB сделать шаблон даты 99.99.9999 ? Сделать руками такой шаблон в Excel (c записью в макрос) и после смотреть что он туда нарисовал

a_sidorov: Чтобы дата корректно отображалась в Excel, нужно дату преобразовать в строку, откуда Excel знает, что на входе дата и в каком зашифрованном виде? Например, так oSheet:Cells( nLine, nI ):Value := If( ValType( xValue )=="D", DtoC( xValue ), If( ValType( xValue )=="N", xValue , ; If( ValType( xValue )=="L", If( xValue ,".T." ,".F." ), cValToChar( xValue ) ) ) )

Haz: Andrey пишет: NumberFormat := '@' Никаких проблем не испытываю при прямой записи даты в Excel. Единственное в hbwin пустую дату необходимо заменить на nil. Указание @ в нумберформате говорит, что следующие данные это строка. Может в этом проблема

Andrey: Haz пишет: Указание @ в нумберформате говорит, что следующие данные это строка. Может в этом проблема В HBOLE.LIB работало, в HBWIN.LIB - нет. Делаю следующее: [pre2] aDim := { DATE()-nLine, "901010"+HB_NtoS(10+nLine), .... } FOR nI := 1 TO LEN(aDim) cType := VALTYPE(aDim[nI]) xValue := aDim[nI] oSheet:Cells( nLine, nI ):Value := xValue IF cType == "D" // преобразуем в текстовый формат //oSheet:Cells( nLine, nI ):NumberFormat := '@' // работает //xValue := StoD( DTOS(xValue) ) // for HBOLE - oSheet:Cells( nLine, nI ):SET( "NumberFormat", 'm/d/yy' ) // дата ячейка - было ранее oSheet:Cells( nLine, nI ):NumberFormat := 'm/d/yy' // дата ячейка - НЕ РАБОТАЕТ, вылет по ошибке ELSEIF cType == "N" .....[/pre2]

Alex_Cher: Мужики, пособите ... создаю Excel, необходимо закрепить верхнюю часть таблицы на экране - макрос выдает " ActiveWindow.FreezePanes = True " вставляю в MiniGUI в разных комбинациях не проходит ... что не так ?

Dima: Alex_Cher Примерно так oExcel:Sheets():Select() oExcel:ActiveWindow:SplitRow := 11 // :SplitCol oExcel:ActiveWindow:FreezePanes := .t.

Alex_Cher: Dima пишет: Примерно так Dima - спасибо большое все нарисовалось,.. удачи тебе и всех благ ....

Pasha: В HBOLE.LIB работало, в HBWIN.LIB - нет. Удивительно, но дельфийский народ жалуется на такой же трабл (хоть у них нет hbole): http://citforum.ck.ua/programming/delphi/excel/

Dima: Как правильно конвертнуть макрос под Harbour ? ExecuteExcel4Macro "SHOW.DETAIL(1,212,FALSE,,2)" Пробовал так oExcel:Application:ExecuteExcel4Macro("SHOW.DETAIL(1,212,FALSE,,2)") Не пашет Проехали (надо было свернуть группы) Сделал так oSheet:Outline:ShowLevels(1)

vvv: Всем доброго дня! Возник вот такой интересный вопрос. Более-менее полноценная работа с Excel подразумевает наличие на компьютере установленного офиса. В силу привычки (или упоротости, не знаю) пользуюсь портабельным офисом. Впрочем, это касается не только офиса, предпочитаю использовать портабельные версии нужного ПО, если они имеются. Собственно вопрос в том, можно ли в связке с харбором как-то использовать вместо установленного офиса портабельный?

Pasha: У меня на работе как раз не установлен MS Office (уже 7 лет обхожусь без него). Скачаю portable, посмотрю.

Dima: vvv пишет: Собственно вопрос в том, можно ли в связке с харбором как-то использовать вместо установленного офиса портабельный? Не попробуешь , не узнаешь... Для начала проверь , будет ли создаваться OLE объект Excel

SergKis: vvv пишет схема работы с xml должна работать ( см. тему http://clipper.borda.ru/?1-4-0-00001250-000-0-0-1541685579 ) т.е. получаем file.xml и запускаем excel file.xml

vvv: Dima пишет: Для начала проверь , будет ли создаваться OLE объект Excel Похоже, не создается. Вот текст ошибки из примера "OLE" --------------------- Internal Error Handling Information --------------------- Subsystem Call ....: TOleAuto System Code .......: -1 Default Status ....: .F. Description .......: CO_E_CLASSSTRING Operation .........: TOLEAUTO:NEW Involved File .....: Dos Error Code ....: 0 SergKis пишет: схема работы с xml должна работать Не, xml не подходит. Суть работы в следующем: открыть xls файл (приходит со стороны), кое-что поменять и сохранить (с сохранением форматирования) под новым именем. В принципе, есть работающий костыль на Йокселе, но Йоксель рандомно затирает формулы и приходится постоянно контролировать результат. Иногда еще теряется формат ячеек, тоже рандомно. Причем потери возникают именно при открытии файла.

SergKis: vvv Если надо менять и присутствуют формулы ..., зачем искать приключений с portable, йоксель, просто установите excel. Есть, конечно, LibXL (можно читать, писать и т.д.), но она платная

vvv: Да сам не знаю, почему ексель не хочется ставить. Может азарт какой "а можно ли без".

PSP: Даже в Википедии написано, что технология OLE использует архитектуру «толстого клиента», то есть сетевой ПК с избыточными вычислительными ресурсами. Это означает, что тип файла либо программа, которую пытаются внедрить, должна присутствовать на машине клиента. Например, если OLE оперирует таблицами Microsoft Excel, то программа Excel должна быть инсталлирована на машине пользователя https://ru.wikipedia.org/wiki/Object_Linking_and_Embedding

vvv: PSP пишет: Даже в Википедии написано, что цитата: технология OLE использует архитектуру «толстого клиента», то есть сетевой ПК с избыточными вычислительными ресурсами. Это означает, что тип файла либо программа, которую пытаются внедрить, должна присутствовать на машине клиента. Например, если OLE оперирует таблицами Microsoft Excel, то программа Excel должна быть инсталлирована на машине пользователя А вот здесь просто интересно, что вложено в данном конкретном случае в понятие "инсталлирована". Портабельный excel присутствует, но он "не инсталлирован", однако работает.

SergKis: vvv пишет Может азарт какой "а можно ли без" В качестве фантазии\приключения (не пробовал) и азарта "а можно ли без". Вариант vba и макросов с назначением вып. макроса на клавишу Ctrl+Shift+... и попытки посылать из hb окну excel этих клавиш для выполнения нужного макроса (после run portable excel file.xls)

PSP: vvv пишет: А вот здесь просто интересно, что вложено в данном конкретном случае в понятие "инсталлирована". Портабельный excel присутствует, но он "не инсталлирован", однако работает. По-моему, у понятия "инсталлирована" нет двойного смысла. Оно однозначно. "Неинсталлированный" excel работает сам по себе, но система о нем ничего не знает и поэтому не может создать экземпляр объекта на основании этого экселя.

vvv: PSP пишет: "Неинсталлированный" excel работает сам по себе, но система о нем ничего не знает и поэтому не может создать экземпляр объекта на основании этого экселя. Вот и хочется либо сообщить системе об этом екселе, либо, зная его месторасположение, использовать его мозги.

vvv: SergKis пишет: В качестве фантазии\приключения (не пробовал) и азарта "а можно ли без". Вариант vba и макросов с назначением вып. макроса на клавишу Ctrl+Shift+... и попытки посылать из hb окну excel этих клавиш для выполнения нужного макроса (после run portable excel file.xls) А можно попробовать в праздники, если делать нечего будет.

Dima: vvv пишет: А можно попробовать в праздники, если делать нечего будет. Погугли на предмет Portable Excel Create Ole Object

Pasha: Скачал portable office с рутрекера: https://rutracker.org/forum/viewtopic.php?t=5526478 а касперский его сразу грохнул, говорит мол: бяка, лечение невозможно Нет ли ссылки без бяки ?

Dima: Pasha Забей в поиске на рутрекере лучше так "Portable Office 2003" Всего 12 ссылок

Pasha: Да я видел эти сборки, в комментариях пишут: на win10 не идет, а у меня как раз она. Автор сборок смотрю тот же

Dima: Pasha Паш забей на портабл , так как служба не загружена , ни чего не выйдет стандартными методами и придется выкручиваться.

PSP: vvv пишет: Вот и хочется либо сообщить системе об этом екселе, либо, зная его месторасположение, использовать его мозги. "Сообщить" системе можно очень просто: инсталлировать)) Всё остальное - фантазии. Это всё равно, что иметь автомобиль без мотора и думать, что автомобилю можно просто "сообщить", что мотор лежит в гараже и машина будет ехать только от этого "знания")))

Dima: По ходу можно пробнуть , но не факт что сработает. Грузим Excel (portable) через hb_processOpen (например) После пробуем что то типа oExcel := GetActiveObject( "Excel.Application" )

Haz: Портабле приложения запускаются в своем окружении "песочнице" и этому приложению подсовывается наследие системы где его подготовили. А вовсе не наоборот. OLE точно работать не будет. VBA и макросы будут. Но об этом уже выше написано. Более того, если даже всю подготовку сделать, к примеру в xml, то система не будут иметь ассоциированного приложения с этим xml. Нужно руками запустить портабле ехель и руками открыть файл xml. Подобные приложения используются для работы в ручном режиме при угрозе влететь на лицензию. Для автоматизации они не годятся в привычном смысле. А для людей творческих, ничто не мешает из своей программы на харбуре запустить портабле ехель и дождавшись загрузки управлять ехелем нажимая на кнопки на его морде посылая соответствующие сообщения определенным окнам ехеля. Но это еще то шапито.

SergKis: Haz пишет Подобные приложения используются для работы в ручном режиме при угрозе влететь на лицензию Для работы одну лицензию можно приобрести, не ней проделывать манипуляции с документами через ole и раздавать для использования в portable excel на другие pc. Будет дешевле, во всех смыслах, чем "шапито"

Haz: SergKis пишет: Для работы одну лицензию можно приобрести, Согласен, но это к заказчику. А у заказчика в голове мозг по другому работает.

Vlad04: Посмотрел примеры - в основном выгрузка в Excel. У меня задача обратная - нужно прочесть данные с большого Excel файла (несколько десятков тысяч записей ). Размеры файла могут быть разные, т.е. не знаю сколько строк. Все читается через OLE, но очень долго, несколько минут. Как ускорить ?

Dima: Vlad04 Можно погуглить "чтение файла excel ole" А строки можно сразу посчитать

Pasha: Свойство Value относится к объекту Range. Можно присвоить Range диапазону ячеек внутри строки, и получить Value как массив. Можно получить значения сразу нескольких строк как двумерный массив.

Vlad04: Pasha Попробую построчно считывать. При записи подобным образом скорость кратно возрастает

Haz: Vlad04 пишет: нужно прочесть данные с большого Excel файла Если это просто чья то выгрузка в Excel - читать можно через ODBC

Vlad04: Haz Выгрузка чья-то, но формат определённый. Попробовал читать в массив - построчно быстрее,чем по клеточно - а если всю таблицу в массив, так вообще улёт, совсем немного отстает от DBF. Через ODBC, наверно, скорость будет как с родной таблицей ?

Haz: Vlad04 пишет: Через ODBC, наверно, скорость будет как с родной таблицей ? В принципе не тормозит. Где-то был пример чтения через ODBC, если сам не найдёшь, могу поискать у себя. Точно баловался лет 7 назад, тк была задача чтения и записи больших таблиц Excel.

Vlad04: Небольшой косочек кода решил выложить, так как с некоторыми моментами пришлось повозиться ExcelApl - имя объекта Excel при открытии oAS := ExcelApl:ActiveSheet() Количество строк в Excel странице mlast := ExcelApl:ActiveSheet:Range("A1"):CurrentRegion:Rows:Count Копирование в переменную mCel (объявлена, как {}) необходимой области страницы Excel - 3 столбца на всю высоту.В столбцах числовые значения (2) и в одном - Дата. mCel:=oAS:Range('D'+Alltrim(Str(1,5))+':F'+Alltrim(Str(mlast,5))):Value Обработка nn:=2 for i:=2 to mlast // собственно данные со второй строки nWsrst:=(datTek - mCel[i,1] )/365.25 // в итоге число, исходное значение ДАТА nPOL:=Int(mCel[i,2] ) // число nSmk:= Int(mCel[i,3]) // число .... next i

Vlad04: Формат исходного документа csv и xls. Оффис 2003.

Dima: Vlad04 хз я считаю строки и столбцы примерно так a:=oSheet:UsedRange:Rows:Count b:=oSheet:UsedRange:Columns:Count это после oWorkBook := oExcel:Workbooks:Open(cfile) oSheet := oExcel:ActiveSheet()

Haz: Vlad04 Через ODBC, наверно, скорость будет как с родной таблицей Попробуй этим , просто интересно Выгрузки в Excel где первая срока - имена полей а потом сам массив данных читает влет ODBCDemo.prg [pre2] #require "rddsql" #require "sddodbc" #include "simpleio.ch" #include "dbinfo.ch" REQUEST SDDODBC, SQLMIX REQUEST HB_CODEPAGE_RU1251, HB_CODEPAGE_RU866 PROCEDURE Main() #if defined( __HBSCRIPT__HBSHELL ) rddRegister( "SQLBASE" ) rddRegister( "SQLMIX" ) hb_SDDODBC_Register() #endif Set( _SET_DATEFORMAT, "yyyy-mm-dd" ) HB_SETCODEPAGE( "RU1251" ) rddSetDefault( "SQLMIX" ) ? "Connect:", rddInfo( RDDI_CONNECT, { "ODBC", "Driver={Microsoft Excel Driver (*.xls)};DriverId=790;Dbq=TEST.XLS;" } ) ? "Use:", dbUseArea( .T., , "select * from sheet1", "test" ) ? "Alias:", Alias() ? "DB struct:", hb_ValToExp( dbStruct() ) wait dbGoTop() Browse() dbCloseArea() RETURN [/pre2] Browse там для наглядности, обработку можно сделать в цикле while !eof() ... end, доступ к полям через fieldget( n ) свой XLS переименуй в TEST.XLS и кинь в папку с программой. ВАЖНО ярлычек с данными в EXL должен называться sheet1 или поправь в исходнике под свое название С MiniGui под консоль собирается так c:\MiniGui\batch\compile.bat ODBCDemo /l hbodbc /l odbc32 /l sddodbc /l hbsqldd /c %1 %2 %3 %4 %5 %6 %7 %8 %9

Dima: Pasha пишет: В office 2013 и office 2010 с последними обновлениями появилась новая неприятная хворь: При открытии документа методом Excel:Workbooks:Open происходит или ошибка открытия, или зависание при выполнении метода. Хворь проявляется у Excel, и иногда у Word. У меня шаблоны документов хранятся на letodb сервере. Перед открытием я их копирую в папку temp из getenv('temp'). Делаю точно так же и в 2003 работает норм. В 2010 падаем при открытии. Сделал пару тестов с тем же файлом Excel минуя копирование по сети , проблемы нет. Курил тему https://answers.microsoft.com/ru-ru/office/forum/office_2010-excel/%D0%B7%D0%B0%D1%89%D0%B8%D1%89%D0%B5%D0%BD%D0%BD/d2647c06-cb06-4a3c-a1db-2821e8a0d561 не помогло Курил так же Meтод Open http://www.taurion.ru/excel/pril1/7 и решения не увидел Что делать я хз

Pasha: Я тоже не нашел общего ответа, как решить элу проблему. Иногда эксель сходит с ума и начинает чудить. Из последних случаев: Эксель отказывался открывать определенный документ, по каким-то причинам считая его подозрительным Согласился открывать только после того, как я пересохранил документ именно этим экселем Другой случай: win_oleCreateObject("Excel.Application") на одном компьютере стал стабильно выдавать непонятную ошибку и сваливаться. Причем word там же работал без проблем Я уже собрался переустанавливать паршивца, когда заметил, что если Excel уже работает, открыт другой документ, то win_oleCreateObject тоже работает. Иногда не открывает файл из определенной папки, после копирования его в другую начинает открывать. Рекомендации по ссылке я тоже отрабатывал, не помогало Начиная с версии 2010 поганец сам решает, открывать ему файл или нет.

Dima: Pasha пишет: Я тоже не нашел общего ответа, как решить элу проблему. Я обнаружил один момент , писал выше. Если с тем же XLS файлом проделывать манипуляции по открытию его не важно из какой папки , минуя копирование по сети то все открывается нормально. Видать какой то атрибут цепляется к файлу после его копирования по сетке........вот его бы обнулить как то..

PSP: Dima пишет: Видать какой то атрибут цепляется к файлу после его копирования по сетке........вот его бы обнулить как то.. http://winitpro.ru/index.php/2015/03/17/kak-windows-opredelyaet-chto-fajl-skachan-iz-interneta/

Dima: PSP Пасиб за ссылку. Что делать с этими атрибутами из Harbour не понятно.. Но посетила мысль , я взял файлик XLS по сети и сложил локально. Далее читаю его содержимое через hb_MemoRead , файлик локально убиваю и после пишу в файл с таким же именем через hb_memowrit По идее от этого атрибута и следа не останется

Haz: Dima пишет: .вот его бы обнулить как то.. Попробуй так StrFile(FileStr(cFile ), cFile) создастся локальный файл PS Дим не заметил твое последнее с memowrit - по сути одно и тоже написали

Dima: Haz пишет: по сути одно и тоже написали бывает

PSP: Нормальный способ)) Костыль, конечно, но 100%-ый))

Pasha: Вот описание работы с альтернативными потоками средствами winapi: https://habr.com/ru/post/46990/ Можно сделать обертку этих вызовов на харборе. Насколько я понял, для получения списка потоков файла надо использовать функцию NtQueryInformationFile. А для удаления потока подойдут и обычные файловые функции.

Haz: Dima пишет: его бы обнулить как то.. Дим все оказалось просто; Ferase( cFile + ":Zone.Identifier") удаляет этот альтернативный поток не трогая сам файл. Более того стандартные файловые функции могут читать и писать в эти потоки.

Pasha: Эти потоки - просто идеальное хранилище для вирусов. Интересно, антивирусы их проверяют ? Это не так тривиально, надо получить еще список потоков, а имена их могут быть разными

Haz: Pasha пишет: Это не так тривиально, надо получить еще Да побаловался сегодня с ними. Держать там можно все что угодно. Можно протокол программы вести, можно dbf туда сунуть все, можно скрытые ресурсы. Из плюсов - все автоматом переезжает в другую папку при копировании и недоступно простому юзеру. Из минусов - только в ntfs, при удалении основного потока все это добро пропадает ( перекомпилил программу, заменил и привет) и стандартными способами получить список альтпотоков не удалась ( но это вопрос времени) В целом использовать можно, работают все файловые функции. Можно создать записать прочитать и удалить. Паша, спасибо за наводку. Ей уж лет 10 но узнал впервые Ps. Не знаю как на потоки отреагирует бекап. Скорее всего прозевает м это плохо, придётся перед бекапом их выводить из тени.

Pasha: Есть комп с недавно установленной системой (win7), и соответственно офисом 2007 На этом компе Excel отказывается открывать любой документ посредством механизма ole, т.е вызов oExcel:Workbooks:Open( cFile, 0 ) всегда возвращает ошибку. Сам Excel работает без замечаний. При этом word нормально открывает документы через ole Рядом стоит комп-близнец, на который устанавливался тот же софт, и такой проблемы нет. Отключение антивируса не помогает. Настройки параметров безопасности Excel тоже не дают результата Снес офис с очисткой реестра, установил другой 2007-й. Проблема осталась Снес 2007-й, поставил 2010-й. Проблема осталась И я капитулировал. Вот сижу, переписываю нужные функции для OpenOffice. Всяко лучше, чем сносить ось Это не просьба о помощи.

Pasha: Началась настоящая Excel-эпидемия В одной организации наблюдается массовая переустановка windows: winxp -> win7, соответственно с переустановкой Office (2007) Можно собирать статистику На большинстве компьютеров Excel удалось уговорить открывать документы следующим образом: Сначала надо просто запустить Txcel, и только при запущенном продукте документы открываются На одном компьютере Excel открывать документы категорически отказался, пришлось переделывать все формы под LibreOffice, а формы есть сложные, то еще удовольствие. PS Пошла еще эпидемия mail.ru. После переключения на новый интерфейс на winxp большинство браузеров поддерживает не всю функциональность. Только старый firefox вроде бы работает нормально

Haz: Pasha пишет: Началась настоящая Excel-эпидемия скорее пакет офиса кривой. На разных системах с разными офиса и никогда таких проблем не было. Ну кроме некоторых команд по ole, c которыми лень разбираться. Как открывается? Олей наверно?

Pasha: олей конечно. Устанавливаю ос и офис не я, и устанавливается все наверняка с одного пакета. Но я в позапрошлом посте писал, что боролся уже полным сносом офиса и переустановкой, пробовал даже два разных офиса, причем эти офисы в тех случаях, когда я их устанавливаю вместе с ОС, такой проблемы не дают Я с таким сталкиваюсь нечасто, но сталкиваюсь. Поскольку борьба с офисом отнимает массу времени, причем борьба бесполезная, я уже сразу не ввязываюсь, и устанавливаю libreoffice

Pasha: Вот кстати не могу найти аналог в OpenOffice для очистки границ. В Excel это выглядит так: oBorder := oCell:Borders(7) oBorder:LineStyle := xlNone в OpenOffice: oBorder := oRange:TableBorder oLine := oBorder:LeftLine и далее у oLine есть свойства: OuterLineWidth, InnerLineWidth, LineDistance устанавливаю все в 0, затем oBorder:LeftLine := oLine oRange:TableBorder := oBorder эффекта никакого

Pasha: В OpenOffice нет аналога записи макроса, как в Excel, это заметно усложняет работу с ним Но оказывается, такая фича таки есть Надо открыть Сервис - Параметры - Расширенные возможности, и поставить флажок на Включить запись макросов (ограничено) Хоть и ограничено, но больше, чем ничего. Вот сижу, изучаю полученные макросы

Pasha: Научился я таки убирать границы. Оказалось, что для диапазона ячеек эти методы почему-то не работает, приходится очищать в цикле для всех ячеек диапазона

Haz: Pasha пишет: Поскольку борьба с офисом отнимает массу времени, причем борьба бесполезная, Давно перешёл на xmlxls, разработка дольше но работает оч быстро. Олю пользу только для косметики.

Allcome: Поставлена задача в ячейку вставить картинку (логотип) в ячейку. Помогите кто чем может, пожалуйста!

Dima: Варианты oRange:=oSheet:Range(osheet:cells(2,1),osheet:cells(2,1)) oExcel:ActiveSheet:Shapes:AddPicture(GetTempFolder()+"\logo.png",.F., .T., oRange:Left, oRange:Top, 78,59) или oSheet:Cells( 2, 1 ):select() oExcel:ActiveSheet:Pictures:Insert(GetTempFolder()+"\logo.png"):select()

Allcome: Спасибо огромное! Буду пробовать.

Andrey: Allcome пишет: Поставлена задача в ячейку вставить картинку (логотип) в ячейку. Помогите кто чем может, пожалуйста! Смотри пример \MiniGUI\SAMPLES\Advanced\Tsb_Export\demo.exe модуль Tsb4xlsOle.prg

Allcome: Dima, спасибо, всё получилось!

Andrey: Прога на МиниГуи, делаю экспорт в Эксель. У меня всё нормально, у заказчика - хрень. Дата переводиться вот в таком виде: Куда копать ?

Pasha: Andrey пишет: Куда копать ? Принудительно поставить формат ячейки - текстовый, и загонять в нее не дату, а DTOC(<дата>)

Andrey: Pasha пишет: Принудительно поставить формат ячейки - текстовый, и загонять в нее не дату, а DTOC(<дата>) Не особо хорошее решение, а вдруг другим юзерам потребуется сортировка в Экселе по дате. Что-то в Экселе сломалось, хотелось бы там починить.

Dima: https://excel2.ru/articles/otobrazhenie-v-ms-excel-formata-daty-v-tekstovoy-stroke

SergKis: Andrey пишет Не особо хорошее решение, а вдруг другим юзерам потребуется сортировка в Экселе по дате. Можешь формировать дату hb_dtoc( dDate, "yyyy-mm-dd")

Andrey: SergKis пишет: Можешь формировать дату hb_dtoc( dDate, "yyyy-mm-dd") Отлично ! А тип ячеек менять надо ?

SergKis: Andrey hb_dtoc(dDate, "yyyy-mm-dd") возвращает строку ( как и DtoC(...) ), а второй параметр это шаблон, т.е. SET DATE TO GERMAN и DtoC(dDate) даст dd.mm.yyyy с hb_dtoc() можешь динамически менять формат отображения на выходе строка Что бы не парится,что у клиента на машинах, всегда дату подаю в excel строкой, а бывает, что excel пытается съесть в свой формат, тогда добавляю слева пробел или &npsp;

SergKis: PS &nbsp; правильно букву просмотрел

Pasha: Если заглянуть в кишки, то hbole преобразовывает значение типа дата в тип VT_DATE, и передает экселю команду присвоения для Value. Если формат ячейки общий, то эксель, а он же гипер-супер-смарт, то есть умный, может преобразовать формат ячейки в дату, тогда значение отображается правильно. А может не преобразовать, оставить его общим, тогда дата отображается как число. Поэтому лучше формат ячейки указать самому. Можно не текстовый формат, а дату: oCell:NumberFormat := "m/d/yyyy"

Sergy: Тоже в свое время намучился с датами. И апострофы подставлял, и ячейки форматировал. Всё не то. Потом понял, что Excel хочет видеть дату только так: yyyy/mm/dd Работает на всех версиях Excel и Windows. Плюс форматировать дополнительно ячейки не нужно.

Dima: Sergy пишет: Потом понял, что Excel хочет видеть дату только так: yyyy/mm/dd Это ты про какой вариант ? oCell:NumberFormat := "yyyy/mm/dd" или hb_dtoc( dDate, "yyyy/mm/dd") ?

Sergy: Dima пишет: Это ты про какой вариант ? oCell:NumberFormat := "yyyy/mm/dd" или hb_dtoc( dDate, "yyyy/mm/dd") ? Про содержимое ячейки: hb_dtoc( dDate, "yyyy/mm/dd") После этого форматировать дополнительно уже редко нужно. Например, если только заголовки столбцов/колонок в специфическом виде, например "янв 20", или "Декабрь 2019"

Andrey: Всем привет ! А как задать показ листа в масштабе 75% ?

Pasha: Запись макроса сломалась ?

Andrey: Pasha пишет: Запись макроса сломалась ? Да блин разбираться надо, а вдруг уже это кто-то давно решил... У меня в экспорте цвет сломался, пока с этим разбираюсь.

Dima: Andrey пишет: А как задать показ листа в масштабе 75% ? oExcel:ActiveWindow:Zoom:=88

Andrey: Dima пишет: oExcel:ActiveWindow:Zoom:=88 СПАСИБО !

Oskar_AAA: Добрый день, коллеги. используем: xHarbour version...: xHarbour build 1.2.1 Intl. (SimpLex) (Rev. 6476) xHarbour built on..: Jun 11 2009 09:38:24 C/C++ compiler.....: Borland C++ 5.5.1 (32 bit) перешли на OC Win10 pro + Excel 365 и нет прав администратора. Программа формирует 500 отчетов в dbf и конвертирует их в Xlsx, затем последовательно собирает их в сводный (511 листов) Excel файл. Программа валится в разных местах (файлах) при конвертации в Xlsx Subsystem Call ....: Excel.Application:ACTIVEWORKBOOK:SHEETS System Code .......: 3 Default Status ....: .F. Description .......: DISP_E_MEMBERNOTFOUND Operation .........: PASTE Arguments .........: Involved File .....: Dos Error Code ....: 0 Trace Through: ---------------- до этого была OC Win8x64+ Excel 2010 и права администратора, ошибки не было, или была очень редко. На ноутбуке OC Win10 pro +Excel 365 и права администратора - проблем нет. ниже пример кода вызов Excel oExcel :=ToleAuto():New("Excel.Application") oExcel_S:=ToleAuto():New("Excel.Application") oExcel :Visible=.F. oExcel :Set("DisplayAlerts",.F.) oExcel :Workbooks:Open(Dbf_File) oBook :=oExcel:ActiveWorkBook oSheet :=oExcel:ActiveSheet oAs :=oExcel:ActiveSheet() oRange :=oExcel:ActiveCell:SpecialCells(xlLastCell) cRecno :=oRange:Row cColumn :=oRange:Column ///// oAs:Range(oAs:Cells(2,2),oAs:Cells(cRecno,cColumn)):Select() oAs:Range(oAs:Cells(2,2),oAs:Cells(cRecno,cColumn)):Copy() // MS Excel и переключение на него oExcel_S:Workbooks:Open(Day_Excel) oExcel_S:Set("DisplayAlerts",.F.) oExcel_S:Visible :=.F. // запуск сводного Excel oBook_S :=oExcel_S:ActiveWorkBook oAs_S :=oExcel_S:ActiveSheet() oSheet_S:=oBook_S :Sheets(1):Select() oSheet_S:=oBook_S :Sheets(1) oSheet_S:Cells(1,1):Value=Hb_OemToAnsi(Ll_Say) oSheet_S:Cells(2,1):Value=Hb_OemToAnsi(Ff_Say) oSheet_S:Cells(2,3):Value=Dtoc(Date())+','+Substr(Time(),1,5) oAs_S:Range(oAs_S:Cells(1,1),oAs_S:Cells(2,8)):Font:Bold:=.T. // сводный Excel oSheet_S:=oBook_S :Sheets(1):Select() oBook_S :=oExcel_S:ActiveWorkBook oAs_S :=oExcel_S:ActiveSheet() oSheet_S:=oBook_S :Sheets(1):Select() oSheet_S:=oBook_S :Sheets(1) oAs_S :Cells(6,1):Select() oSheet_S:Paste() Hb_GtInfo(HB_GTI_CLIPBOARDDATA, "") в чем может быть проблема? ИБ не дают права локального администратора.... На виртуальной станции, там права админа - программа работает корректно (8х64 +Excel2010)

Dima: Oskar_AAA пишет: перешли на OC Win10 pro + Excel 365 и нет прав администратора. А если их временно дать , что то изменится ?

Haz: Переодически ловил непредсказуемые ошибки при копипасте В OLE. Если просто конвертить dbf в xlsx, забудьте про OLE. Посмотрите на xlsxml. В разы быстрее и не зависит от капризов екселя. ps... 500 отчётов... я бы не выдержал, а ексель вообще уйдёт в

Dima: Haz пишет: Посмотрите на xlsxml Хороший вариант по ходу ЗЫ Сам я пока на него не перешел но где то в далеких планах есть такой переход

SergKis: Dima пишет Сам я пока на него не перешел но где то в далеких планах есть такой переход У нас, не давно, опять было сообщении об аресте и конфискации парка pc у фирмы, за использование продуктов майкрософт без лицензии (за этим следит созданная спец. организация). Дима, как только ваши депутаты сообразят, что тут клондайк, тоже соорудят такое. Ведь "чем дальше в лес" ES тем больше бабла рубят. Многие имеют в лучшем случае одну лицензию на excel и работают по очереди или openoffice и вариант xlsxml очень удобен, т.к. без ole

Dima: SergKis пишет: Ведь "чем дальше в лес" ES тем больше бабла рубят. Да в этот ES , у нас только когда все разворуют , вот тогда может и сообразят..........

rvu: Haz пишет: Переодически ловил непредсказуемые ошибки при копипасте В OLE. Я заполнял небольшие таблицы, всё нормально было. А какие ошибки при каких операциях?

Haz: rvu пишет: А какие ошибки при каких операциях? Всё настроишь, все работает и вдруг через год или два валится на pagesetup или printquality это из последних. Часто на формат данных вдруг ругаться начинает. На копи пасте из одного листа в другую книгу, где то на сотом цикле может рухнуть.. Да и в целом очень зависимый механизм от версии офиса. При этом если произошла ошибка эусель как правило зависает в пямяти процессом и срубается только диспетчером тк так его не видно. Но самое нетерпимое это скорость работы этой Оли.

Oskar_AAA: Добрый день, коллеги. Dima, если есть права админа, то работает корректно. Пробовали 2 раза и оба раза все ОК. Haz - Если просто конвертить dbf в xlsx, забудьте про OLE. Посмотрите на xlsxml. В разы быстрее и не зависит от капризов екселя. - где можно скачать итд?

Oskar_AAA: Немного о проекте. Продукт для банка (аналитика), 1996 год начало (Clipper5.1). Сейчас более 60 DBF (для примера. проводки 10 млн. 4ГБ, остатки по счетам 6 млн. 600 МБ, курсы валют, филиалы, клиенты итд). За операционный день импорт данных (в среднем) данные: 272 тыс.счетов, 8 тыс. остатков по балансу филиалов, 120 тыс.проводок, 236 тыс. клиентов итд.... Использую тандем с 2011 года: 1. обработка данных и выгрузка во временный DBF(ы) 2. Excel - конвертация в Xlsx, форматирование, цвета, шрифты итд, загрузка макета(ов) и запись временного Xlsx 3. Excel - загрузка макета(ов) отчета и копирование из временного Xlsx. PS: Версия программы 2005 года (xharbour), 106 млн проводок, 95 млн. остатки по счетам, 15ГБ.... на LETODB переводил в 2006 году, но остановился (ушел с банковской тематики, сейчас вернулся...)

Oskar_AAA: Haz - Всё настроишь, все работает и вдруг через год или два валится на pagesetup или printquality это из последних. Часто на формат данных вдруг ругаться начинает. На копи пасте из одного листа в другую книгу, где то на сотом цикле может рухнуть.. Да и в целом очень зависимый механизм от версии офиса. При этом если произошла ошибка эусель как правило зависает в пямяти процессом и срубается только диспетчером тк так его не видно Один в один, аналогичная ситуация...

SergKis: Oskar_AAA http://clipper.borda.ru/?1-4-80-00001250-000-0-0-1541685579

SergKis: PS hb -> \core-master\extras\hbxlsxml/*.*

Haz: Oskar_AAA пишет: где можно скачать итд? Сергей уже указал правильное направление напишу примерчик конвертации DBF2XML ( XML этот такой же родной для EXCEL как и XLSX ) в примере конвертил CUSTOMER.DBF из поставки минигуи , но привязки к структуре нет , можно пихнуть любой другой ( на мемополя проверку тоже не делал ) [pre2] #require "hbxlsxml" REQUEST DBFCDX, DBFFPT PROCEDURE Main() LOCAL oXml, oSheet, cFile := "customer.xml" LOCAL n,oStyle LOCAL aStr := {} LOCAL cType := "" RDDSETDEFAULT('DBFCDX') Set CENTURY ON Set Deleted ON Set Date GERMAN SET Date FORMAT 'DD.MM.YYYY' REQUEST HB_CODEPAGE_RU1251, HB_CODEPAGE_RU866, HB_CODEPAGE_UTF8 EXTERN hb_StrToUTF8 Set( _SET_DATEFORMAT, "dd.mm.yyyy" ) USE ("CUSTOMER.DBF") SHARED NEW ALIAS "CUSTOMER" aStr := CUSTOMER->(DBSTRUCT()) // Создаем объект XML oXml := ExcelWriterXML():New( cFile ) oXml:setOverwriteFile( .T. ) oXml:setCodePage( "RU1251" ) // Определяем Лист oSheet := oXml:addSheet( "Sheet1" ) // Определяем стиль названия отчета oStyle := oXml:addStyle( "Title" ) oStyle:alignHorizontal( "Left" ) oStyle:alignVertical( "Center" ) oStyle:SetfontName( 'Arial' ) oStyle:SetfontSize( 12 ) oStyle:setFontBold() //Определяем стили шапки колонок oStyle := oXml:addStyle( "HDR" ) oStyle:Border( "All", 2, "Automatic", "Continuous" ) oStyle:alignHorizontal( "Center" ) oStyle:alignVertical( "Center" ) oStyle:alignWraptext() oStyle:setFontBold() oStyle:alignWraptext() // Определяем стили колонок cAlign := "Left" for n := 1 TO Len( aStr ) cType := aStr[n][2] switch cType Case "D" cAlign := "Center" Exit Case "C" cAlign := "Left" Exit Case "N" cAlign := "Right" Exit end Switch oSheet:columnWidth( n, aStr[n][3] * 8 ) oStyle := oXml:addStyle( "F" + NToC(n) ) oStyle:Border( "All", 1, "Automatic", "Continuous" ) oStyle:alignHorizontal( cAlign ) oStyle:alignVertical( "Center" ) oStyle:fontSize( 10 ) next // Пишем название отчета nRow := 1 oSheet:writeString( nRow, 1, "Пример выгрузки DBF2XML " , "Title" ) // Пишем шапку nRow++ nRow++ For n := 1 To Len( aStr ) oSheet:writeString( nRow, n, aStr[n][1] , "HDR" ) End oSheet:cellHeight( nRow, 1, 22 ) nRow++ //Данные While !CUSTOMER->(eof()) oSheet:cellHeight( nRow, 1, 15 ) For n := 1 To CUSTOMER->(FCOUNT()) uData := CUSTOMER->(FieldGet(n)) cType := ValType( uData ) switch cType Case "N" oSheet:writeNumber( nRow, n, uData, "F" + NToC(n) ) Exit Case "C" oSheet:writeString( nRow, n, uData, "F" + NToC(n) ) Exit Case "U" oSheet:writeString( nRow, n, '', "F" + NToC( n) ) Exit Case "T" oSheet:writeDateTime( nRow, n, hb_Ttoc(uData), "F" + NToC( n) ) Exit Case "D" oSheet:writeDateTime( nRow, n, Dtoc(uData), "F" + NToC( n) ) Exit Case "L" oSheet:writeString( nRow, n, IIF(uData, 'да' , 'нет'), "F" + NToC( n) ) Exit End Switch Next CUSTOMER->(dbSkip(1)) nRow++ End oXml:writeData( cFile ) RETURN [/pre2].

Haz: Oskar_AAA пишет: где можно скачать итд? только компилировать с библиотекой из поставки минигуи, она к русскому языку приучена.

Pasha: xlsxml конечно работает в разы быстрее, чем ole, но подходит для ограниченного круга задач. Скажем сейчас мне надо выбрать данные из почти 300 таблиц xls, похожей, но различной структуры. Делаю средствами ole. Долговато, но время здесь некритично, это разовая выборка данных для дальнейшей конвертации. Или типовая задача: скачать бланк документа с сайта, пометить в нем ячейки и заполнить его данными. xlsxml тут никак не подходит.

Haz: Pasha пишет: xlsxml тут никак не подходит. Не подходит для этой цели. Xlsxml это вывод. Для чтения или OLE или ado/odbc если читаем простую таблицу. Если нужно прочесть сложный отчёт в Excel, то пока только OLE. Соглашусь, что не хватает альтернативы тормознутому OLE. Есть коммерческие библиотеки, но не все готовы за них платить ради разовой задачи

SergKis: Pasha пишет Делаю средствами ole. Долговато, но время здесь некритично, это разовая выборка данных для дальнейшей конвертации. Или типовая задача: скачать бланк документа с сайта, пометить в нем ячейки и заполнить его данными. Можно не использовать ole, о получать xml и разбирать его. Для похожих таблиц - тоже однотипная операция. Данные бланков то же могут быть и в xml и json, этого становится больше (xls[x] уже почти не встречается), а xlsxml со своей задачей справляется

Haz: SergKis пишет: Можно не использовать ole, о получать xml и разбирать его. тоже думал над этим вопросом, но получить xml из excel можно не совсех версий Excel. До xlsx БЫЛ двоичный BIFF, потом XML. OLE наплевать на версию и работает везде, но работает медленно и капризно. Json бесспорно удобнее xml, получить хеш массив и делать то ничего не надо, все уже разложено по ключам. Жаль не все его дают, а как пишет Паша - скачай бланк и заполни.

SergKis: Haz пишет получить xml из excel можно не совсех версий Excel. До xlsx БЫЛ двоичный BIFF, потом XML. OLE наплевать на версию и работает везде, но работает медленно и капризно. Уже не помню таких версий. И если бы ole не имела глюков, особенно на компах клиентов, где чужие админы, то не возникали бы вопросы, которые выше. С xml все надежнее и в сети все больше данные только в xml или json (и можно выбрать вариант). С json проще, его и выбираешь и бланков xls[x] по обмену данными уже нет, если только сам разрабатываешь и применяешь в технологии обмена.

Haz: SergKis пишет: Уже не помню таких версий А они есть В остальном согласен. json лидирует, за ним xml и в конце этого паравоза устаревший обмен ввиде "скачай и заполни". Изначально тема была как быстро выгрузить в Excel, ответ- xlsxml. Как по мелочам допилить красоту, ответ - ole ( тк вывод в xlsxml, линеен, а красоту надо наводить рандомно) . И в каком формате организовать обмен, ответ json/xml.

Oskar_AAA: Добрый вечер, коллеги. Спасибо за ответы. Всем успехов и удачи... Будем изучать и тестировать.

Pasha: Насчет админ прав - это мысль, проверю на проблемных компьютерах, где проказник-эксель отказывается работать Как раз подвернулся случай проверить - не помогло

Oskar_AAA: у меня все ка и было. Нотник -ОК. Рабочая станция - свалился на 145 файле в копирасте

Pasha: В последнее время я больше ориентируюсь на работу с LibreOffice. Механизм ole для него более тормозной, чем для Excel, структура объектов сложнее, но нет таких капризов и сюрпризов, как с Excel Или делаю работу с бланком xsl[x] как для одного, так и для второго пакета, и использую либо Excel-вариант, либо oo.

Andrey: Pasha пишет: В последнее время я больше ориентируюсь на работу с LibreOffice. Чем он отличается от OpenOffice ? Сам не ставил его, а вот экспорт из МиниГуи, как в примере MiniGUI\SAMPLES\Advanced\Tsb_Export\demo.prg что-то не пошёл у меня у заказчика.

Pasha: Andrey пишет: Чем он отличается от OpenOffice ? С точки зрения программирования - ничем. А нравится, не нравится - не тот вопрос. Да и использовать его заказчику необязательно. Положим на проблемных компах не получается работа с Excel. Формирую xls-документ через LibreOffice, а пользователь открывает его уже экселем Про OO ему и знать не надо

Oskar_AAA: Добрый вечер, коллеги. Поставили 2-ой ПК. Win10x64+Office2019 с правами администратора. Ошибок нет, весь отчет выгрузился без проблем. Коллеги, есть ли пример кода запуска LibreOffice под xHarbour? Всем Спасибо за участие и консультации! Успехов и удачи....

Andrey: Oskar_AAA пишет: Коллеги, есть ли пример кода запуска LibreOffice под xHarbour? Смотри пример в МиниГуи - :\MiniGUI\SAMPLES\Advanced\Tsb_Export Под хХарбор можно его переделать.

Oskar_AAA: Добрый день. Спасибо

Dima: Pasha пишет: Насчет админ прав - это мысль, проверю на проблемных компьютерах, где проказник-эксель отказывается работать Сегодня нарвался на ошибку да на ровном месте а ведь все работало :) Оказалось что отвалился принтер по умолчанию (или помог кто то , не было умалчиваемого принтера , хотя был) и штуки вида oSheet:PageSetup........... начали дружно бить ошибки

Andrey: Всем привет ! А как можно записывать свои формулы при создании листа экселя ? Допустим есть такая формула =RC[-13]-RC[-14], при создании листа записываю эту формулу как текст в ячейку. А как потом указать Экселю, что это формула и нужно пересчитать ? Ни разу таким не занимался. А заказчик хочет свои формулы править. Вот и сделал ТСБ с формулами по нужным колонкам, а в экселе идёт вставки ячейки как текст, а нужно как формула.

Pasha: А как можно Все что делает эксель, можно заставить его делать через ole. А как ? Включить запись макросов, и посмотреть, как он это делает, и сделать так же. На тот случай, когда запись опять сломалась, вместо oRange:Value надо присваивать строку в oRange:Formula

Pasha: Dima пишет: Сегодня нарвался на ошибку да на ровном месте а ведь все работало :) Да, эксель дуреет, если нет принтера, и все, что связано с форматирование страниц, отваливается. Тоже нарывался на такое

Andrey: А можно где то в Экселе записать 3-4 значения и чтобы юзер их не мог отредактировать ?

Dima: Andrey пишет: А можно где то в Экселе записать 3-4 значения и чтобы юзер их не мог отредактировать ? Попробуй руками в EXCEL , если получится то можно и в Harbour перенести

Andrey: Так я и спрашиваю, где это можно сделать. Есть ли места, где юзер не видит этих данных ? По простому можно наверное сделать на втором листе сразу в первой ячейки, допустим DATE(), вторая ячейка - фио юзера (кто делал отчёт), третья - период расчёта. Можно эти данные сделать белым цветом и юзер их не увидит, а мне в другой проге это нужно будет. Но юзер может тупо удалить второй лист и мои данные "накрылись". Вот и спрашиваю, где можно расположить такие данные, чтобы ОБЫЧНЫЙ юзер не смог исправить такие данные.

Dima: ну можно заблочить колонку(и) под пароль и скрыть её

ZAlex: информация к размышлению: если смотреть свойства файла (закладка Подробно), то можно узнать кто создал и сохранил файл. Но это возможно, если Office зарегистрирован. К тому же , эти данные как-то надо прочесть. (я не знаю как, пока)

nick_mi: Andrey пишет: А можно где то в Экселе записать 3-4 значения и чтобы юзер их не мог отредактировать В Excel есть защита и листа и защита ячеек на листе, можно воспользоваться

PSP: Andrey пишет: Можно эти данные сделать белым цветом и юзер их не увидит Ставишь курсор на ячейку и вверху видишь ее содержимое.

Haz: Andrey пишет: А можно где то в Экселе записать 3-4 значения и чтобы юзер их не мог отредактирова Можно, как уже написали , есть стандартные методы защиты ячеек. При записи макроса видно как их использовать , включая работу с паролем на изменение.

Andrey: Спасибо всем за отзывы. Нашёл вроде интересное решение проблемы. Писать данные во второй лист (как обычно он всегда присутствует), а потом его скрыть. Думаю обычный юзер не станет этот лист открывать и тем более удалять.

Dima: Andrey пишет: Думаю обычный юзер не станет этот лист открывать и тем более удалять. Можно еще проще , писать можно нужные тебе данные ну скажем в строке с номером 10 000 и сделать белым шрифтом на белом фоне. Ни кто и искать не станет

Andrey: Dima пишет: Можно еще проще , писать можно нужные тебе данные ну скажем в строке с номером 10 000 и сделать белым шрифтом на белом фоне. Это да, так можно. НО !!! попробуй отправить на печать такой лист. Удивишься сколько бумаги уйдёт... Юзер будет просто в ауте.

MIKHAIL: Andrey пишет: Нашёл вроде интересное решение проблемы. Писать данные во второй лист (как обычно он всегда присутствует), а потом его скрыть. Думаю обычный юзер не станет этот лист открывать и тем более удалять. можно сделать суперскрытый лист, он только через макрос VB может быть открыт

Andrey: Да думаю этого достаточно будет для обычного юзера. Для других целей нужны другие подходы. Сделал тест, кому будет интересно:[pre2] oExcel:WorkBooks:Add() oExcel:Visible := .T. oBook := oExcel:ActiveWorkBook oSheet := oExcel:ActiveSheet() oSheet := oBook:Sheets(2) oSheet:name := "МОЁ_НЕ_ТРОГАТЬ!" // имя листа изменить nCnt := oBook:Sheets:Count // количество листов в книге cMsg := "Количество листов в книге = " + HB_NtoS(nCnt) + ";" FOR EACH oSheet IN oBook:WorkSheets cMsg += oSheet:Name + ";" NEXT cMsg := StrTran(cMsg, ";", CRLF ) MsgInfo(cMsg) oSheet:Cells:Font:Name := "Arial" oSheet:Cells:Font:Size := 12 oSheet:Cells( 3, 1 ):Value := "City:" oSheet:Cells( 3, 2 ):Value := "Moskow" ....... // далее запись во 2 лист oSheet:Visible := .F. // скрыть лист 2 oBook:Sheets(3):Select() // перейдём на 3 лист oSheet := oExcel:ActiveSheet() oSheet:Visible := .F. // скрыть лист 3 oBook:Sheets(1):Select() // вернутся на 1 лист oSheet := oExcel:ActiveSheet() oSheet:name := "Мой_отчёт" // имя листа изменить ...........[/pre2] Исправления и правка приветствуются ! Как считать со скрытого листа, даже ещё и не знаю и не пробовал ....

Dima: Andrey пишет: Как считать со скрытого листа, даже ещё и не знаю и не пробовал .... Да точно так же

MIKHAIL: Andrey пишет: Исправления и правка приветствуются ! Как считать со скрытого листа, даже ещё и не знаю и не пробовал .... макросы скрытые листы могут не видеть, нужно сначала открыть Sheets("List").Visible = -1 // делаем видимым Sheets("list").Visible = 2 // 2 -суперскрытый, 0 - обычный скрытый

Andrey: Всем привет ! Опять беда с этими версиями экселя. У меня код работает, у других тоже, а у некоторых вылет. Вот код:[pre2] // Используем Ole из HBWIN.lib IF ( oExcel := win_oleCreateObject( "Excel.Application" ) ) == NIL ..... ENDIF oExcel:WorkBooks:Add() oBook := oExcel:ActiveWorkBook oSheet := oExcel:ActiveSheet .... // вызов допольнительного внешнего блока дообработки таблицы Tuning2Xls(hProgress, oSheet, oExcel) ... FUNCTION Tuning2Xls(hProgress, oSheet, oExcel) oBook := oExcel:ActiveWorkBook oSheet := oExcel:ActiveSheet() oSheet := oBook:Sheets(2) // вот здесь вылетает oSheet:name := "my_formuls" // имя листа изменить[/pre2] Ошибка вот такая: Error WINOLE/1007 (0x8002000B): SHEETS (DOS Error -2147352567) Args: [1] = N 2 --------------------------------- Stack Trace --------------------------------- Called from WIN_OLEAUTO:SHEETS(0) Called from TUNING2XLS(160) in module: Source\table_f5dogTsbD40export.prg Called from (b)TOEXCEL7(129) in module: Source\table_f5dogTsbD40export.prg Called from BRW7XLSOLE(408) in module: Source\Tsb7xlsOle.prg Как исправить код, чтобы на всех Экселях работало ?

Dima: может как то так oSheets := oWorkBook:Sheets oSheets:Item(2):Select() oSheet := oExcel:ActiveSheet

Pasha: В параметрах экселя можно задать количество листов при создании новой книги. Может там 2-го листа вообще нет ?

Andrey: Pasha пишет: В параметрах экселя можно задать количество листов при создании новой книги. Может там 2-го листа вообще нет ? У меня на 2003 работает, а на 2016 нет. Сам смотрел у заказчика - прога падает. Смотри почту.

Pasha: Как исправить код, чтобы на всех Экселях работало ? Судя по моему опыту - никак. Эксель непредсказуем, хочет - работает, не хочет - нет. Тут вопрос или элементарный - надо проверить количество листов в книге, или включается режим "бешеного экселя", как я его называю, когда чудо-продукт либо совсем отказывается открывать книгу, либо сваливается на элементарных командах, вроде Sheets(2) 2003 еще стабильно работает, а начиная с 2007 начинаются чудеса.

Andrey: Dima пишет: может как то так oSheets := oWorkBook:Sheets oSheets:Item(2):Select() oSheet := oExcel:ActiveSheet Поставил у себя, работает. Жалко что заказчик отключился и нет Экселя 2016 чтобы проверит. Спасибо Dima !

Pasha: Смотрю доку по VBA Excel: Worksheets.Item Property (Excel) Item is the default member for a collection. For example, the following two lines of code are equivalent. ActiveWorkbook.Worksheets.Item(1) ActiveWorkbook.Worksheets(1) То есть, обращение oBook:Sheets(2) и oBook:Sheets:Item(2) эквивалентны, и работать будут одинаково. Это все равно, что сравнивать на харборе выражения aItem[i, j] и aItem[ i ][ j ] Они либо оба сработают, либо оба не сработают

Andrey: Нашёл 2016 эксел. Не пашет... Нашёл в чём дело. Оказывается в 2016 экселе при создании файла создаётся только ОДИН лист. Паша оказался прав !!!

Pasha: Файл - Параметры - Общие - При создании новых книг - Число листов - ... Но таки да, похоже в 2016 по умолчанию стоит 1, а не 3, как в предыдущих версиях. Но походу это значение меняется, так что надо проверять Sheets:Count

Andrey: Переход на лист по индексу: [pre2]oSheets:Item(3):Select() // перейдём на 3 лист[/pre2] А как переходить по имени листа ? Лист1, Лист2, ...

Andrey: Блин, столько мороки с порядком добавления листа. В старых версиях порядок: Лис1,Лист2,Лист3 В 2016 при добавлении становиться наоборот: Лис3,Лист2,Лист1 А ещё на Лист1 уже готовая таблица нарисована. Вынос мозга чтобы на всех версиях работало... Сделал.

Dima: Andrey пишет: Вынос мозга чтобы на всех версиях работало Нет ни какого выноса , нужно найти правильный подход , думай

LYSK: Здравствуйте, коллеги! Есть необходимость сформировать книгу EXCEL с двумя листами программно, причем на компе, где ни EXCEL, ни ОО не установлены. Т.е необходима библиотека, дающая проге на HARBOUR записывать в XLS напрямую, без OLE. Уверен, что такая есть. Что посоветуете?

Haz: LYSK пишет: Что посоветуете? xmlxls. В поиске по форуму и примеры Андрея Tsb_brw2xml ЗЫ правда не XLS готовит а XML который понимается Excel

Andrey: LYSK пишет: Уверен, что такая есть. Что посоветуете? \MiniGUI\SAMPLES\Advanced\Tsb_Export\demo.exe Далее кнопка "Export", далее менюшка "Export to Excel (xls-files)" Используется метод из библиотеки oBrw:Excel2() - запись файла без использования OLE, запись напрямую в файл. Протестируй пример с этим меню, должен работать. Исходник метода \MiniGUI\SOURCE\TsBrowse\h_tbrowse.prg Переделать этот метод под себя я думаю можно. LYSK пишет: Есть необходимость сформировать книгу EXCEL с двумя листами программно, Кол-во листов при создании 1. Второй не знаю как сделать.

Haz: Andrey пишет: Кол-во листов при создании 1. Второй не знаю как сделать. Все в исходниках [pre2] oSheet1 := oXml:addSheet( "Sheet1" ) // Если нужно еще , добавляем еще oSheet2 := oXml:addSheet( "Sheet2" ) [/pre2] Дале запись в нужный шит

Dima: LYSK Либа LibXL libxl_v3.8.3.0_with_sn_dxmod.7z https://mega.nz/#!l5U02CaL!kyyEN1CsQQRrZT9Vtdrs1v49X-CaSlA0JQ97MLOyrtc

Oskar_AAA: Добрый день, коллеги. Вроде как решил проблему с работой в MS Excel. Поставил inkey(inkey_Time) между вызовами MS Excel для обработки.... inkey_Time=0.75 обработка 1 файла с Copy Paste inkey(Inkey_Time) обработка 2 файла Inkey(Inkey_Time)

Andrey: Нашёл на просторах инета... случайно. Графики на Экселе http://mail.hmgforum.com/viewtopic.php?t=6600 Всяко-разное: [pre2]******************************************************************************************************* COMMENTS OldComment := Sheet1:Range("A1"):Comment:Text // GET COMMENT NewComment := OldComment + " Edited comment" Sheet1:Range("A1"):Comment:Delete() // DELETE COMMENT Sheet1:Range("A1"):AddComment (NewComment) // ADD COMMENT ******************************************************************************************************* outline oExcel:Selection:ClearOutline() // disable outline ******************************************************************************************************* Freeze Panes oSheet:cells(2,11):SELECT() oExcel:ActiveWindow:FreezePanes := .T. // Enable oExcel:ActiveWindow:FreezePanes := .F. // Disable ******************************************************************************************************* Auto Filter // AutoFilter (Field, Criteria1, Operator, Criteria2, SubField, VisibleDropDown) A. oSheet:Range("A1:U1"):AutoFilter() // ENABLE B. oSheet:Range("A1:U1"):AutoFilter(8,"RED") // ENABLE AND SET Criteria1 ==> (Field, Criteria1) C. oSheet:Range("A1"):AutoFilter(8,"RED",xlOr,"BLUE") //xlOr ==> (Field, Criteria1, Operator, Criteria2) D. oExcel:Worksheets("AOI_DAILY"):Range("A1"):AutoFilter(11,">70",xlAnd, "<320") // xlAnd ==> (Field, Criteria1, Operator, Criteria2) oExcel:Selection:AutoFilter() // Disable ******************************************************************************************************* Sort // SortFields:Add(KEY? SortOn? Order? CustomOrder? DataOption? cRange := "P1" _1st_Range := oExcel:Sheets("AOI_DAILY"):Range( cRange ) // SET RANG of 1ST KEY cRange := "E1:E924" _2nd_Range := oExcel:Sheets("AOI_DAILY"):Range( cRange ) // SET RANG of 2ND KEY cRange := "F1:F924" _3rd_Range := oExcel:Sheets("AOI_DAILY"):Range( cRange ) // SET RANG of 3RD KEY cRange := "J1:J924" _4th_Range := oExcel:Sheets("AOI_DAILY"):Range( cRange ) // SET RANG of 4TH KEY cRange := "A1:U924" SORT_Range := oExcel:Sheets("AOI_DAILY"):Range( cRange ) // SET RANG of SORT Area With OBJECT oExcel:Worksheets("AOI_DAILY"):Sort() :SortFields:Clear() :SortFields:Add(_1st_Range,xlSortOnCellColor,xlDescending,xlSortNormal):SortOnValue:Color:=RGB(255, 255, 0) // BY Cell Color & Descending :SortFields:Add(_2nd_Range,xlSortOnValues,xlAscending,xlSortNormal) :SortFields:Add(_3rd_Range,xlSortOnValues,xlAscending,xlSortTextAsNumbers) // Text As Numbers :SortFields:Add(_4th_Range,xlSortOnFontColor,xlAscending,xlSortNormal):SortOnValue:Color:=RGB(0, 0, 0) // BY FONT Color :SetRange(SORT_Range) :Header := xlYes :MatchCase := .F. :Orientation :=xlTopToBottom :SortMethod := xlPinYin :Apply() EndWith ******************************************************************************************************* Merge CELLS A. oSheet:Range("A1:D1"):Merge() .OR. B. cRange := "A16:B17" oSheet:Range(cRange):Select() oExcel:Application:CutCopyMode:= .F. with OBJECT oExcel:Selection() :HorizontalAlignment := xlCenter :VerticalAlignment := xlCenter :WrapText := .F. :Orientation := 0 :AddIndent := .F. :IndentLevel := 0 :ShrinkToFit := .F. :ReadingOrder := xlContext :MergeCells := .F. EndWith oExcel:Selection:Merge() ******************************************************************************************************* Check if merged If oSheet:Range("A22"):MergeCells // .OR. If oSheet:Range("A22:B22"):MergeCells // .OR. If oSheet:Cells(22, 1):MergeCells oSheet:cells(T,1):SELECT() // SET activecell // .OR. oSheet:Range("A25"):SELECT() // SET activecell MSGINFO(oExcel:Activecell:MergeArea:Rows:Count()) // How many rows are merged? MSGINFO(oExcel:Activecell:MergeArea:Columns:Count()) // How many columns are merged? MSGINFO(oExcel:Activecell:MergeArea:Cells:Count()) // How many cells are merged? MSGINFO(oSheet:Range("A25"):VALUE()) MSGINFO(oExcel:activecell:MergeArea:Address()) // What's the merged range address? EndIf ******************************************************************************************************* MOVE SHEET oExcel:Application:Worksheets("Sheet1"):Move(after:=oExcel:Application:Worksheets("Sheet3")) oExcel:Worksheets("Sheet2"):Move(before:=oExcel:Worksheets("AOI_DAILY")) oExcel:Worksheets("Sheet3"):Move(after:=oExcel:Worksheets(oExcel:Sheets:Count())) oExcel:sheets("Sheet3"):Move(after:=oExcel:sheets(oExcel:Sheets:Count())) ADD SHEET oExcel:Sheets:Add:Name:=oSheet:range("a3"):value() //add a Sheet before the ActiveSheet oExcel:Worksheets:Add(after:=oExcel:Worksheets("Sheet5")):Name:="NewSheet" oExcel:Worksheets:Add(before:=oExcel:Worksheets("Sheet5")):Name:=oSheet:range("a3"):value() oExcel:sheets():Add(after:=oExcel:sheets("Chart2")):Name:="NewSheet" // sheets() CAN BE USED WITH "CHART" OR "SHEET" COPY SHEET oExcel:Worksheets("AOI_DAILY"):Copy(before:=oExcel:Worksheets("Sheet5")) oExcel:Worksheets("AOI_DAILY"):Copy(after:=oExcel:Worksheets(oExcel:Sheets:Count())) oExcel:sheets("AOI_DAILY"):Copy(after:=oExcel:sheets("Sheet3")) oExcel:ActiveSheet:Name:="MySheetName" // ASSIGN NAME ******************************************************************************************************* PasteSpecial // Paste Formulas/Formats oSheet:Range("D2:E2"):COPY() cRange:="D3:E30" oSheet:Range(cRange):Select() oExcel:Selection:PasteSpecial(xlPasteFormulas,xlPasteSpecialOperationNone) // Paste Formulas oExcel:Selection:PasteSpecial(xlPasteFormats,xlPasteSpecialOperationNone) // Paste Formats oExcel:Selection:PasteSpecial(Paste:=xlPasteFormats,Operation:=xlPasteSpecialOperationNone) ******************************************************************************************************* AutoFill A. Define Rang sourceRange := oSheet:Range("I2:I2") fillRange := oSheet:Range("I2:I30") .OR. sourceRange := oExcel:Sheets( "AOI_DAILY" ):Range("I2:I2") fillRange := oExcel:Sheets( "AOI_DAILY" ):Range("I2:I20") B. AutoFill the Rang sourceRange:AutoFill(Destination:=fillRange,TYPE:=xlFillFormats) .OR. oSheet:Range("I2:I2"):AutoFill(fillRange,xlFillFormats) ******************************************************************************************************* GET SHHETs / CHARTs NAME ws:=oExcel:sheets() wc:=oExcel:Charts() A. Returns Only the names of each worksheets MSGINFO(oExcel:Worksheets:Count()) For Each ws In oExcel:Worksheets() MSGINFO(ws:Name()) Next For i = 1 To oExcel:Worksheets:Count() MSGINFO(oExcel:Worksheets(i):Name()) Next i B. Returns the names of each worksheets & Charts MSGINFO(oExcel:Sheets:Count()) For Each ws In oExcel:Sheets MSGINFO(ws:Name()) Next For i = 1 To oExcel:Sheets:Count() MSGINFO(oExcel:sheets(i):Name()) Next i C. Returns Only the names of each Charts MSGINFO(oExcel:Charts:Count()) For Each wc In oExcel:Charts() MSGINFO(wc:Name()) Next For i = 1 To oExcel:Charts:Count() MSGINFO(oExcel:Charts(i):Name()) Next i ******************************************************************************************************* Chart Add, Copy & Move oExcel:Charts:Add(After:=oExcel:Charts("NEW CHART 2")):Name:="NEW CHART 3" oExcel:Charts:Add(before:=oExcel:Worksheets("Sheet3")):Name:=oSheet:range("C3"):value() oExcel:Charts("NEW CHART 2"):Copy(after:=oExcel:sheets("NEW CHART 1")) oExcel:ActiveSheet:Name = "My new Chart" oExcel:Charts("NEW CHART 2"):Move(before:=oExcel:Charts("NEW CHART 1")) *******************************************************************************************************[/pre2]



полная версия страницы