Board logo

標題: excel VBA calculate 的疑問 [打印本頁]

作者: shy    時間: 2013-5-8 12:08     標題: excel VBA calculate 的疑問

儲存格A1 會從外部接收資料 (DDE接收開盤價)
例如 台積電開盤價
我設定一個目標 (100元)
如果當天開盤>=100
就會執行送單

我GOOGLE了一下
網路上都是教使用 calculate 和change這兩個指令
因為接收外部資料
所以只能使用calculate

但我試了一下
發現兩個問題
1. 就是我主動改A1(改為101)的值, 並不會主動送單, 而是要從VB裡面按執行才會送出單子.

2. 一旦按了執行, 就會一直送單送個不停, 有沒有辦法設定成A1變動1次, 送單1次呢??
作者: GBKEE    時間: 2013-5-8 13:03

回復 1# shy
  1. Option Explicit
  2. Private Sub Worksheet_Calculate()  '工作表重算事件
  3.     '主動改A1(改為101)的值之後:  A1沒有=公式 不會啟動 [工作表重算事件]
  4.     '如A1=公式   公式的值有變動 會啟動 [工作表重算事件]
  5.     Application.EnableEvents = False
  6.     '程式碼.(修改到工作表公式參照到的儲存格)......  '當沒有 Application.EnableEvents = False'會一直送單送個不停
  7.     '程式碼.(修改到工作表公式參照到的儲存格)......
  8.     '程式碼.......
  9.     Application.EnableEvents = True
  10. End Sub
  11. Private Sub Worksheet_Change(ByVal Target As Range) '工作表內容有變動事件
  12.     '主動改A1(改為101)的值之後:  A1沒有=公式 會啟動 [工作表內容有變動事件]
  13.     Application.EnableEvents = False
  14.     '程式碼..(有修改到工作表的內容)....  '當沒有 Application.EnableEvents = False'會一直送單送個不停
  15.     '程式碼..(有修改到工作表的內容)....
  16.     '程式碼..(有修改到工作表的內容)....
  17.     Application.EnableEvents = True
  18. End Sub
複製代碼
  1. EnableEvents 屬性
  2. 請參閱套用至範例特定如果指定物件能觸發事件,則本屬性為 True。讀/寫 Boolean。
  3. 本範例會在儲存檔案之前停用事件,從而使 BeforeSave 事件不會發生。
  4. Application.EnableEvents = False
  5. ActiveWorkbook.Save
  6. Application.EnableEvents = True
複製代碼

作者: shy    時間: 2013-5-9 09:47

回復 2# GBKEE
昨天試了幾次
發現還是不行
我後來發現是我問的不好
我重新問我的問題好了


儲存格A1 會從外部接收資料 (DDE接收開盤價)
例如 台積電成交價
假設儲存格B1是昨日收盤價(DDE接收收盤價)
如果當天成交價大於收盤價
就會執行送單

但是我寫出來的程式
都要用人工去按執行
沒有辦法自動
我GOOGLE了一下
網路上都是教使用 calculate 和change這兩個指令
因為接收外部資料
所以只能使用calculate

但我試了一下
發現兩個問題
1. 我是利用C1=A1-B1
     if C1 >0 Then 執行
     然後回到sheet1, 發現C1>0的時候不會自己動
     一定要回到VB裡面按執行, 但按了執行, 就會一直送單送個不停, 有沒有辦法設定成C1變動1次, 只執行1次呢??

2.  我用了
     Application.EnableEvents = False
    雖然不會一直執行動作
    但是回到sheet1, 發現C1>0 的時候還是不會自己動作
    難道要用change這個指令嗎? (但C1是公式阿...)
    但是用了change
    會出現一個狀況
    就是每次按執行
    就會出現巨集的框框出來....
作者: GBKEE    時間: 2013-5-9 10:43

回復 3# shy
請你上傳檔案才清楚問題癥結
作者: shy    時間: 2013-5-9 11:17

本帖最後由 shy 於 2013-5-9 11:19 編輯

回復 4# GBKEE

我沒有辦法上傳檔案
好怪喔

我貼我寫的

        A                 B                   C                  D
1   代碼           商品            成交            昨收
2   2330          台積電           115.5           114.5
3                       
4                                                                             1

我打在this workbook

Private Declare Function PlaceOrderVB Lib "TC_Excel_Addin.xll" (ByVal OrderInfo As String) As String
Option Explicit
------------------------------------------------------------------------------------
Private Sub Worksheet_calculate()

Dim tmpResult As String
Dim OrderInfo_1 As String
tmpResult = ""

OrderInfo_1 = "" ' 裡面是個資, 下單的設定
tmpResult = PlaceOrderVB(OrderInfo_1)
MsgBox tmpResult

Application.EnableEvents = False

If Range("D4") >= 0 Then
PlaceOrderVB (OrderInfo_1)

End If


End Sub
作者: GBKEE    時間: 2013-5-9 11:47

回復 5# shy
2# 程式中你要恢復ㄚ
09.    Application.EnableEvents = True
17.    Application.EnableEvents = True

[attach]14932[/attach]
作者: shy    時間: 2013-5-9 12:13

回復 6# GBKEE

我知道要這樣上傳阿
但是按了上傳後
會出現
對不起,不支持上傳此類擴展名的附件。
這樣的字...
作者: shy    時間: 2013-5-9 12:24

回復 6# GBKEE

變成這樣??
Private Declare Function PlaceOrderVB Lib "TC_Excel_Addin.xll" (ByVal OrderInfo As String) As String
Option Explicit
------------------------------------------------------------------------------------
Private Sub Worksheet_calculate()

Dim tmpResult As String
Dim OrderInfo_1 As String
tmpResult = ""

OrderInfo_1 = "" ' 裡面是個資, 下單的設定
tmpResult = PlaceOrderVB(OrderInfo_1)
MsgBox tmpResult

Application.EnableEvents = False

If Range("D4") >= 0 Then
PlaceOrderVB (OrderInfo_1)

End If

Application.EnableEvents =ture

End Sub
作者: GBKEE    時間: 2013-5-9 12:27

回復 8# shy
不是 ture 是 TRUE
作者: shy    時間: 2013-5-9 12:52

本帖最後由 shy 於 2013-5-9 12:53 編輯

回復 9# GBKEE

sorry
是true才對

所以是這樣??

Private Declare Function PlaceOrderVB Lib "TC_Excel_Addin.xll" (ByVal OrderInfo As String) As String
Option Explicit
------------------------------------------------------------------------------------
Private Sub Worksheet_calculate()

Dim tmpResult As String
Dim OrderInfo_1 As String
tmpResult = ""

OrderInfo_1 = "" ' 裡面是個資, 下單的設定
tmpResult = PlaceOrderVB(OrderInfo_1)
MsgBox tmpResult

Application.EnableEvents = False

If Range("D4") >= 0 Then
PlaceOrderVB (OrderInfo_1)

End If

Application.EnableEvents =true

End Sub


還是不會自己動....
作者: GBKEE    時間: 2013-5-9 13:13

本帖最後由 GBKEE 於 2013-5-9 13:19 編輯

回復 10# shy
沒有檔案只好用猜的
Private Sub Worksheet_Calculate()  '預設工作表觸動事件:   工作表重算事件
這程序碼須是在 DEE 公式所在工作表模組中


[attach]14934[/attach]
作者: c_c_lai    時間: 2013-5-9 14:30

回復  GBKEE

我知道要這樣上傳阿
但是按了上傳後
會出現
對不起,不支持上傳此類擴展名的附件。
這 ...
shy 發表於 2013-5-9 12:13

你必須先將相關檔案集中,然後全壓縮成 .rar (使用 Winrar.exe) 檔案,
才可以上傳 ( .rar 檔案)。
作者: shy    時間: 2013-5-11 12:39

回復 11# GBKEE

大哥
這樣好像可以了
但是又有新的問題
現在變成不管有沒有符合條件
都會去執行程式
然後都會出現 msgBox "SUCDEDEDSUCEEDED"
差別只是在於有沒有自動丟單(符合就會自動丟單, 沒有符合就沒有丟單....)
我可以改成
沒有符合條件==> 不動作
有符合條件==> 執行丟單動作==> 才回傳 msgBox "SUCDEDEDSUCEEDED"



我可以請教你一個問題嗎
我這個檔案是外接DDE
你沒有我的軟體
那麼我把檔案上傳到底有甚麼意義?
因為打開後
都是#N/A, 不然就是#REF!
但是我有把我寫的程式碼弄上來阿.....
還是你有辦法解決外接DDE的問題??
作者: GBKEE    時間: 2013-5-11 13:27

回復 13# shy
Q:現在變成不管有沒有符合條件,都會去執行程式,然後都會出現 msgBox "SUCDEDEDSUCEEDED"
  1. Private Sub Worksheet_calculate()
  2.     'DEE 數值有變動 會執行此程式  ********
  3.     Dim tmpResult As String
  4.     Dim OrderInfo_1 As String
  5.     tmpResult = ""
  6.     OrderInfo_1 = "" ' 裡面是個資, 下單的設定
  7.     tmpResult = PlaceOrderVB(OrderInfo_1)
  8.     '***************
  9.     MsgBox tmpResult  '當然都會出現 msgBox "SUCDEDEDSUCEEDED"
  10.     '*************************
  11.     Application.EnableEvents = False

  12.     If Range("D4") >= 0 Then  '這是你說的 符合條件 嗎??
  13.         PlaceOrderVB (OrderInfo_1)
  14.         MsgBox tmpResult  '如果你程式碼置於此 符合條件 才會 msgBox "SUCDEDEDSUCEEDED"
  15.     End If
  16.     Application.EnableEvents = ture
  17. End Sub
複製代碼
Q 我這個檔案是外接DDE,你沒有我的軟體,那麼我把檔案上傳到底有甚麼意義?

10#  Application.EnableEvents =true  ,還是不會自己動....
10#你的回覆:對我還是唰無帳.....

11# 沒有檔案只好用猜的
     Private Sub Worksheet_Calculate()  '預設工作表觸動事件:   工作表重算事件
     這程序碼須是在 DEE 公式所在工作表模組中

請問我11#這回覆對你有幫助嗎??? 如有那把檔案上傳就不必瞎子摸象!!!
作者: shy    時間: 2013-5-11 15:31

回復 14# GBKEE


我把檔案傳上
大哥你在看一下.....

我希望的目標是
符合條件(>=0)=> 執行自動下單(有沒有出現msgbox沒有關係..)
不符合條件=>不要動作,也不用通知..


[attach]14949[/attach]
作者: shy    時間: 2013-5-11 15:35

回復  GBKEE


我把檔案傳上
大哥你在看一下.....

我希望的目標是
符合條件(>=0)=> 執行自動下單( ...
shy 發表於 2013-5-11 15:31


補充一下
符合條件一次=> 只執行一次
作者: GBKEE    時間: 2013-5-11 16:23

本帖最後由 GBKEE 於 2013-5-12 18:58 編輯

回復 16# shy
  1. Private Declare Function PlaceOrderVB Lib "TC_Excel_Addin.xll" (ByVal OrderInfo As String) As String
  2. Option Explicit
  3. Private Sub Worksheet_calculate()
  4.     'Static 陳述式  在程序層次中用來宣告變數並配置儲存空間。以 Static 陳述式宣告的變數,在程式執行期間,會一直保留內容。
  5.     'Boolean 資料型態 Boolean 變數係以 16 位元( 2 個位元組)數字的形式儲存,但只能是 True 或是 False。Boolean 變數的值不是 True 就是 False
  6.     Static Msg(1 To 2) As Boolean      '程式一開始執行時,預設值為 False
  7.     Dim tmpResult As String
  8.     Dim OrderInfo_1 As String
  9.     Application.EnableEvents = False
  10.    
  11.     '**********DEE的內容在這裡執行的用意....???
  12.     tmpResult = ""
  13.     OrderInfo_1 = "" '裡面有個資,所以沒有辦法公開
  14.     tmpResult = PlaceOrderVB(OrderInfo_1)
  15.     '***************************************
  16.    
  17.     '*********猜猜你的想法: 符合條件一次=> 只執行一次
  18.     If Range("D4") >= 0 And Msg(1) = False Then
  19.        '執行一次後:  "D4" 一直是 >= 0,不再執行直到 "D4" < 0 後在次執行
  20.         Msg(1) = True      '一直是 >= 0
  21.         Msg(2) = False     ' < 0  可執行
  22.         
  23.         '********    請看圖示   *********************
  24.         '程式執行期間,一直保留 Msg(1) = True
  25.         '除非...程式重新執行: 程式 預設值為 False
  26.         '****************************************
  27.         
  28.         PlaceOrderVB (OrderInfo_1)
  29.         ' MsgBox tmpResult    執行自動下單(有沒有出現msgbox沒有關係..)
  30.     ElseIf Range("D4") < 0 And Msg(2) = False Then  '符合條件一次=> 只執行一次
  31.         '執行一次後:  如"D4" 一直是 < 0,不再執行直到 "D4" >= 0 後在次執行
  32.         Msg(1) = False   '>= 0 可執行
  33.         Msg(2) = True    '一直是 < 0
  34.         PlaceOrderVB (OrderInfo_1)
  35.         ' MsgBox tmpResult    執行自動下單(有沒有出現msgbox沒有關係..)
  36.     End If
  37.     Application.EnableEvents = True
  38. End Sub
複製代碼
[attach]14950[/attach]
作者: shy    時間: 2013-5-11 22:35

回復 17# GBKEE


大哥
我不懂你所謂的==> DEE的內容在這裡執行的用意....???
你的意思我為什麼加入==> tmpResult= ""
我也不懂阿
我是按照說明書照抄的...

我按大哥的圖照打
有一個新的問題
就是不管Range("D4") 是不是>=0 都會自動送單

大哥你有需要說明書嗎
http://www.touchance.com/download_file/broker/TOUCHANCE_Excel_操作手冊.pdf
這是網址
小妹我沒有辦法上傳
因為壓縮後大於1MB
作者: Hsieh    時間: 2013-5-11 23:27

本帖最後由 Hsieh 於 2013-5-12 15:51 編輯

回復 18# shy
TOUCHANCE說明
  1. tmpResult = PlaceOrderVB(OrderInfo)
  2. tmpResult:請宣告為String,接收函式回傳值。
  3. OrderInfo:請宣告為String,內容為下單字串。
  4. tmpResult數說明:
  5. 變數
  6. 說明
  7. tmpResult
  8. 您可以改變變數名稱,當下單失敗時會回傳一組字串存入
複製代碼
所以,不需考慮你DDE程序
你要以D4 作為下單依據
  1. Private Declare Function PlaceOrderVB Lib "TC_Excel_Addin.xll" (ByVal OrderInfo As String) As String
  2. Option Explicit

  3. Private Sub Worksheet_calculate()

  4. Dim tmpResult As String
  5. Dim OrderInfo_1 As String  '下單的參數

  6. OrderInfo_1 = "" '裡面有個資,所以沒有辦法公開
  7. '這應該是你下單的參數

  8. If Range("D4") >= 0 Then
  9. Application.EnableEvents = False
  10. tmpResult = PlaceOrderVB(OrderInfo_1) '執行你所謂的下單動作
  11. MsgBox "Run PlaceOrderVB OK!:" & tmpResult  '如果有執行就會出現此警示視窗
  12. Application.EnableEvents = True
  13. End If
  14. End Sub
複製代碼

作者: shy    時間: 2013-5-12 16:53

回復 19# Hsieh

大哥
我用你建議的方式試了一下
有一個問題
打開檔案時會執行一次自動送單
然後會出現msgBox
按確定後
會再執行一次自動送單
但就不會出現msgBox了...

也就是都會執行兩次...
作者: shy    時間: 2013-5-12 17:00

回復  Hsieh

大哥
我用你建議的方式試了一下
有一個問題
打開檔案時會執行一次自動送單
然後會出現 ...
shy 發表於 2013-5-12 16:53


都會送出兩次單...
作者: shy    時間: 2013-5-12 17:04

都會送出兩次單...
shy 發表於 2013-5-12 17:00



如果是開啟檔案
那麼都會送出兩次單...
但是之後按執行或儲存格改變的話
就又只執行一次..
作者: GBKEE    時間: 2013-5-12 17:26

本帖最後由 GBKEE 於 2013-5-12 19:28 編輯

回復 18# shy
   Q: 就是不管Range("D4") 是不是>=0 都會自動送單
是我程式沒寫好
17# 30.    ElseIf Range("D4") > 0 And Msg(2) = False Then  '符合條件一次=> 只執行一次
    須改為   ElseIf Range("D4") < 0 And Msg(2) = False Then  
Q:你有需要說明書嗎?
   去瀏覽一下寫的很清楚:  使用Excel收取委託回報,使用Excel查詢帳務 兩節  不是你問的問題嗎!!!

回復 22# shy
只要工作表中的儲存格有公式:例 =A1+C1,且這工作表模組有Sub Worksheet_Calculate()程序
檔案開啟後,每一工作表的 Sub Worksheet_Calculate()程序,都會執行一次
  1. Private Sub Worksheet_Calculate() '活頁簿中每一工作表的重算事件中
  2.     Stop  '請加上後存檔,再開檔案
  3.    '***程式執行到此 可按 F8 一行,一行..的執行程式碼試試看.********
  4.    '程式碼....
  5.     '程式碼....
  6.     '程式碼....
  7.     '程式碼....

  8. End Sub
複製代碼

作者: Hsieh    時間: 2013-5-12 20:43

回復 20# shy
以上程式碼以邏輯來看,開啟檔案會執行重算沒錯,會觸發Worksheet_Calculate程序
在程序內判斷D4是否符合條件而判斷是否執行送單動作
接下來當DDE收到更新後都會觸發Worksheet_Calculate
但是,若D4結果不符合條件也不該有送單動作
而且每次送單後都應該會出現對話方塊才對
實在看不出哪個環節出錯?
作者: shy    時間: 2013-5-12 22:34

回復 24# Hsieh

GBKEE & Hsieh 大哥
目前除了一開啟檔案會送單兩次外
(符合條件會自動送單兩次, 不符合條件就沒有動作...)

其他基本上都沒有問題了
程式的運作
DDE報價跳動==>符合條件==> 自動送單
                                    不符合條件==> 就沒有動作

接下來小妹開始以這個為基礎
開始更進一步的寫作....
非常感謝你們..
作者: shy    時間: 2013-5-13 10:36

回復 25# shy

可以再請教兩個問題嗎
就是只想一開盤只交易一次
之後不管不管符不符合條件
都不在執行自動下單

原因是這樣的
我在測試DDE送單的速度時
發現一件事情
如果儲存格分別是==> 今日開盤價和昨日收盤價
照道理當開盤開之後就會不動了
但是EXCEL還是一直在執行
例如
今日開盤100, 昨日收盤99 ==> 今開-昨收>=0==>符合條件==>執行送單
但之後理論上應該不會再執行送單了
因為這兩個儲存格的值已經不會再動了
但實際狀況卻是一直送單
我猜這是DDE的問題
所以才想乾脆只執行一開盤的那一次
之後不管符合不符合都不再動作

第二個問題是
我發現送單的時間很規律
都是間隔20秒
照理說
DDE若是每秒都會跳動的話
不是應該只間隔1秒嗎
間隔20秒會是EXCEL的問題嗎
若是我想改成間隔1秒的話
是不是可以在EXCEL上面改呢??
作者: GBKEE    時間: 2013-5-13 14:16

回復 26# shy
基本概念:工作表上的DEE公式變動一次,執行Sub Worksheet_Calculate() 一次.

Q 但是EXCEL還是一直在執行              ->股市營業中 : 工作表上的DEE公式會有變動對嗎?

Q 但之後理論上應該不會再執行送單了      ->工作表上的DEE公式有一個以上對嗎?

Q 間隔20秒會是EXCEL的問題嗎?              ->股市營業中,會每秒每分都有交易嗎?
作者: shy    時間: 2013-5-13 19:53

回復 27# GBKEE

Q 但是EXCEL還是一直在執行              ->股市營業中 : 工作表上的DEE公式會有變動對嗎?

工作表上的DDE公式不會有變動, 但是可以確定是EXCEL卻是持續執行.

Q 但之後理論上應該不會再執行送單了      ->工作表上的DEE公式有一個以上對嗎?

工作表上每個儲存格都只有對應一個DDE公式

Q 間隔20秒會是EXCEL的問題嗎?              ->股市營業中,會每秒每分都有交易嗎?

期貨的話, 每秒都會有交易...
作者: GBKEE    時間: 2013-5-13 20:31

回復 28# shy
基本概念:工作表上的公式傳回的數值變動一次,執行Sub Worksheet_Calculate() 一次.
你說工作表上的DDE公式不會有變動: 是公式沒變動,且公式傳回的數值也都不變嗎? (那股市在營業時間中有在交易嗎?)
你說工作表上每個儲存格都只有對應一個DDE公式? 那這工作表上不是有許多儲存格有公式嗎?(不只一個公式對嗎)

17# 的程式碼已修正好,再試一次看看
作者: shy    時間: 2013-5-13 20:54

回復 29# GBKEE

工作表上只有3個儲存格有數字
今日開盤價    昨日收盤價
還有一個儲存格為 今日開盤價-昨日收盤價

所以一開盤之後
數字還有公式就都不會變了....
作者: shy    時間: 2013-5-13 21:07

回復 29# GBKEE


大哥
我覺得應該是DDE的問題, 應該不是程式的問題
因為即使是現在我打開檔案
所有數字都沒有改變的情況之下(公式當然也沒有變)
關掉檔案
EXCEL都會出現==> 檔案已被修改過, 你是否要儲存檔案的msgbox

所以我猜即使都沒有變的情況之下
DDE還是有動作
我猜是一打開檔案
EXCEL就會去抓DDE的資料
所以即使數字沒有變
但是對EXCEL來說
卻是重新抓的
作者: 准提部林    時間: 2013-5-16 10:27

<DDE工作表資料例>
[attach]14994[/attach]

<工作表事件區.程式碼>
Private Declare Function PlaceOrderVB Lib "TC_Excel_Addin.xll" (ByVal OrderInfo As String) As String
Option Explicit

Private Sub Worksheet_Calculate()
Dim tmpResult As String
Dim OrderInfo_1 As String
If Date Mod 7 - 1 > 5 Then Exit Sub   '今天為〔周六.周日〕非交易日.跳出
If Time < TimeValue("08:00:00") Then Exit Sub   '未到開盤.跳出
If Time > TimeValue("13:45:00") Then Exit Sub   '已過收盤.跳出
If [D5] = "已送單" And [D6] = Date Then Exit Sub   '今天已有送單記錄.跳出
If IsError([D4]) Then Exit Sub    'DDE未正確連結,或公式有誤.跳出
If Val([D4]) < 0 Then Exit Sub   '未達目標價.跳出
On Error GoTo 901    '程式執行錯誤時,強制跳至901行,以回復事件觸發,並跳出
'-------------------------------------------
Application.EnableEvents = False
OrderInfo_1 = "" ' 裡面是個資, 下單的設定
tmpResult = PlaceOrderVB(OrderInfo_1)
PlaceOrderVB (OrderInfo_1)
[D5] = "已送單" '送單訊息
[D6] = Date  '送單日期
[D7] = Time  '送單時間
901: Application.EnableEvents = True
End Sub

<備註>
以工作表事件進行DDE動態監視,並不太好掌控,之前有寫過幾個範例,是以〔每秒〕遞迴主程式監視及記錄數據,
可至敝部落格,或網頁搜尋關鍵字〔准提部林 金千里 DDE〕參考相關下載檔(程式碼公開,且有註解),
個人並無操作股票及其它金融商品,也從未使用過DDE,僅憑揣摸寫程式,所以請自行套用,無法做私人的服務。
爾後若有時間.或許也在這論壇建個〔自動記錄DDE〕題分享!

以上純因版主一句〔VBA好難〕,應緣而發! 祝 操作順利




歡迎光臨 麻辣家族討論版版 (http://forum.twbts.com/)