On-line: Andrey, гостей 1. Всего: 2 [подробнее..]
АвторСообщение
Dima
администратор




Пост N: 2372
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 21.05.12 16:52. Заголовок: Снова EXCEL (продолжение)


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

Спасибо: 0 
Профиль
Ответов - 300 , стр: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 All [только новые]


Haz
администратор




Пост N: 1087
Зарегистрирован: 20.02.11
ссылка на сообщение  Отправлено: 15.04.17 22:35. Заголовок: fokinal21 пишет: А ..


fokinal21 пишет:

 цитата:
А как проверить?


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


Спасибо: 0 
Профиль
Петр
постоянный участник


Пост N: 1441
Зарегистрирован: 09.10.06
ссылка на сообщение  Отправлено: 15.04.17 23:47. Заголовок: Haz пишет: Возможн..


Haz пишет:

 цитата:
Возможно есть способ проще, типа похендлу получить статус окна


Валидность хэндла обычно проверяют с использованием WinAPI функции IsWindow()
В MiniGUI функция-враппер носит название IsWindowHandle().

if IsWindowHandle( oExcel:hWnd ) ...




Спасибо: 0 
Профиль
fokinal21



Пост N: 22
Зарегистрирован: 22.09.13
ссылка на сообщение  Отправлено: 16.04.17 11:19. Заголовок: oExcel ..


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

Спасибо: 0 
Профиль
Dima
администратор




Пост N: 6361
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 16.04.17 12:22. Заголовок: fokinal21 пишет: *П..


fokinal21 пишет:

 цитата:
*По рекомендации Dima
oExcel:=nil


? hWnd
? IsWindowHandle(hWnd)

// Результаты: 462230 и .T.

// Итог: oExcel опять живее всех живых, несмотря на oExcel:Quit() и oExcel:=nil



Ну тогда нужно так

oExcel:Quit()
oExcel:=nil


? hWnd:=oExcel:hWnd
? IsWindowHandle(hWnd)

// Итог: результат в студию


Спасибо: 0 
Профиль
Sergy





Пост N: 523
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 16.04.17 12:33. Заголовок: Dima пишет: oExcel:..


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

 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


Т.е. если процесс уже есть в памяти - использовать его, а не создавать новый.

Спасибо: 0 
Профиль
fokinal21



Пост N: 23
Зарегистрирован: 22.09.13
ссылка на сообщение  Отправлено: 16.04.17 16:36. Заголовок: В общем понятно, что..


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

Спасибо: 0 
Профиль
Dima
администратор




Пост N: 6364
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 16.04.17 16:43. Заголовок: fokinal21 пишет: эт..


fokinal21 пишет:

 цитата:
это значит, что попытки выяснить с помощью хендла закрыл юзер окно с табличкой или нет обречены на провал


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


Спасибо: 0 
Профиль
Haz
администратор




Пост N: 1088
Зарегистрирован: 20.02.11
ссылка на сообщение  Отправлено: 16.04.17 18:42. Заголовок: fokinal21 пишет: Мо..


fokinal21 пишет:

 цитата:
Может кто проведет другим путем?


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

Ps в харбуре есть инструмент чтоб этот алгоритм проверить
Будут вопросы пиши. На чтото я смогу ответить на что-то коллеги помогут


Спасибо: 0 
Профиль
fokinal21



Пост N: 24
Зарегистрирован: 22.09.13
ссылка на сообщение  Отправлено: 17.04.17 09:49. Заголовок: Haz пишет: Как опр..


Haz пишет:

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



Пока на все один большой вопрос ?
Чтобы превратить его в несколько маленьких ,стремящихся к 0, можно чуть подробнее и небольшой пример, можно ссылку, если таковой уже есть.

Спасибо: 0 
Профиль
Петр
постоянный участник


Пост N: 1443
Зарегистрирован: 09.10.06
ссылка на сообщение  Отправлено: 17.04.17 11:58. Заголовок: fokinal21 пишет: По..


fokinal21 пишет:

 цитата:
Пока на все один большой вопрос ?
Чтобы превратить его в несколько маленьких ,стремящихся к 0, можно чуть подробнее и небольшой пример, можно ссылку, если таковой уже есть.


Зачем это все прикладному программисту?

fokinal21 пишет:

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


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




Спасибо: 0 
Профиль
Haz
администратор




Пост N: 1089
Зарегистрирован: 20.02.11
ссылка на сообщение  Отправлено: 18.04.17 11:13. Заголовок: fokinal21 пишет: По..


fokinal21 пишет:

 цитата:
Пока на все один большой вопрос ? Чтобы превратить его в несколько маленьких ,стремящихся к 0, можно чуть подробнее и небольшой пример, можно ссылку, если таковой уже есть.



Вот тот самый небольшой пример. Показывает окна их класс и заголовки. В том числе если есть открытая книга в Excel то ее и покажет в списке
 

#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






Спасибо: 0 
Профиль
fokinal21



Пост N: 25
Зарегистрирован: 22.09.13
ссылка на сообщение  Отправлено: 18.04.17 12:15. Заголовок: Всем спасибо за помо..


Всем спасибо за помощь и консультации!

Haz пишет:

 цитата:
Вот тот самый небольшой пример


Буду, по возможности, разбираться с примером...

Спасибо: 0 
Профиль
Dima
администратор




Пост N: 6368
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 18.04.17 12:37. Заголовок: fokinal21 пишет: Бу..


fokinal21 пишет:

 цитата:
Буду, по возможности, разбираться с примером...


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

Спасибо: 0 
Профиль
SergKis
постоянный участник




Пост N: 1410
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 18.04.17 12:42. Заголовок: Dima пишет Пример по..


Dima пишет
 цитата:
Пример по ходу отображается не верно


тут
 
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


Спасибо: 0 
Профиль
Haz
администратор




Пост N: 1090
Зарегистрирован: 20.02.11
ссылка на сообщение  Отправлено: 18.04.17 13:36. Заголовок: SergKis пишет: тут ..


SergKis пишет:

 цитата:
тут


Дима , Сергей , спасибо . Подправил [ и ]

Спасибо: 0 
Профиль
Петр
постоянный участник


Пост N: 1445
Зарегистрирован: 09.10.06
ссылка на сообщение  Отправлено: 18.04.17 15:48. Заголовок: REQUEST HB_LANG_RU8..



 цитата:
 
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




Программа консольная.
Компилировать как-то так hbmk2 myexcel.prg -lhbwin

Запускать
myexcel /c /m
myexcel /g
myexcel /g
myexcel /g

Рекомендую посмотреть, проанализировать и сделать выводы

Интересно будет посмотреть на результат для разных версий Excel

P.S. Excel 2016 работает чудненько.

Спасибо: 0 
Профиль
Dima
администратор




Пост N: 6372
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 18.04.17 16:26. Заголовок: Петр пишет: P.S. Ex..


Петр пишет:

 цитата:
P.S. Excel 2016 работает чудненько.


На 2003 падает на oExcel:MergeInstances и закоментил пока , пересобрал , запустил с ключом /C и упал в цикле на ? w:hwnd


Спасибо: 0 
Профиль
Петр
постоянный участник


Пост N: 1447
Зарегистрирован: 09.10.06
ссылка на сообщение  Отправлено: 18.04.17 16:38. Заголовок: Dima пишет: На 2003..


Dima пишет:

 цитата:
На 2003 падает на oExcel:MergeInstances


Настоящий Эксель начинается с 2013

Dima пишет:

 цитата:
упал в цикле на ? w:hwnd


Припоминаю, что где-то мы уже это обсуждали, у Ворда свойство hwnd есть, у Экселя нет. В 2007(?) вроде уже есть.


Спасибо: 0 
Профиль
Dima
администратор




Пост N: 6374
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 18.04.17 21:21. Заголовок: Петр пишет: Настоящ..


Петр пишет:

 цитата:
Настоящий Эксель начинается с 2013


Кажется в примере не хватает проверки перед его запуском на версию офиса , впрочем это уже обсуждали
в одной из тем , так что кому надо тот сам и допилит.

PS
У многих еще стоит XP и далеко не SP3 , так что заюзать могут офис только ниже 2010

Спасибо: 0 
Профиль
Петр
постоянный участник


Пост N: 1448
Зарегистрирован: 09.10.06
ссылка на сообщение  Отправлено: 18.04.17 22:12. Заголовок: Dima пишет: Кажется..


Dima пишет:

 цитата:
Кажется в примере не хватает проверки перед его запуском на версию офиса



Можно добавить в любом удобном месте
? oExcel:version

И танцевать от результата

Excel 2003 - 11.0
Excel 2007 - 12.0
Excel 2010 - 14.0
Excel 2013 - 15.0
Excel 2016 - 16.0


Спасибо: 0 
Профиль
Ответов - 300 , стр: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 All [только новые]
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 695
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет