Page 2 of 6 FirstFirst 1234 ... LastLast
Results 11 to 20 of 52

Thread: Notes tests. Application.Run.OnTime Multiple Variable Arguments ByRef ByVal

  1. #11
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,458
    Rep Power
    10
    In Support of this Forum Question:
    https://stackoverflow.com/questions/...ication-ontime





    Multiple Variable Arguments to Application.OnTime

    I have fought with the tricky syntax for arguments to Application.OnTime ( or Application.Run, which is similar ) every time I have needed it. I have often gone here https://stackoverflow.com/questions/...ication-ontime , as well as arrived a few times at the other links referenced below in the second post. As often they almost, but not quite, got me there.

    I spent some time making myself some worked examples to reference in the future, and also convinced myself finally that I understand what is going on.

    So I am sharing my solutions , and finally I think I can have a stab at answering thel question regarding concisely explaining / justifying the syntax..

    I am deliberately giving very full explicit code lines for two reasons

    _ 1. Its easy to simplify it to the more usual shortened version if you only need that, but going the other way , from the more common simplified form to the full explicit form, should you need that, is quite hard.

    _ 2.Showing the full explicit code line syntax helps with my attempt at explain the syntax, and so is needed in answering the question fully.


    The full explicit syntax would be needed , for example , to ensure the corrects file were opened, when we want to trigger a macro in a closed workbook. ( In such a case, the closed workbook would be opened. The VBA Application.OnTime code line will do this opening, provided it has the full explicit form )

    I am using 2 example files, the first would be opened , the second can be closed or open , but the second should be in the same folder. ( The reason why it needs to be in the same folder is just for simplified demonstration, - I have organised that demonstration macros will look for the closed workbook in the same folder. In the practice, the closed workbook can be anywhere if you replace exactly this bit , ( including the first " ) , with the full path and file name of the closed workbook

    " & ThisWorkbook.Path & "" & "UverFile.xls

    In other words, you would replace that last bit with something like …_

    C\Elston\Desktop\MyFolder\UverFile.xls

    _ .. giving a complete code line of this sort of form:
    Code:
        Application.OnTime Now(), "'" & ThisWorkbook.Path & "\" & "UverFile.xls" & "'" & "!'Modul1.MacroInUverFile ""465""'": Debug.Print "!'Modul1.MacroInUverFile ""465""'"
    Open workbook - MainFile.xls : https://app.box.com/s/prqhroiqcb0qccewz5si0h5kslsw5i5h

    Module "Modul1" in MainFile.xls
    (This is the main module from which all macros are run)

    See here: http://www.excelfox.com/forum/showth...ll=1#post11861
    http://www.excelfox.com/forum/showth...2070#post12070




    Worksheets Class module of first worksheet "Tabelle1" in MainFile.xls

    Code:
    Option Explicit
    Sub InLisWbFirstWsCodeModule(ByRef Nmbr As Long)
     MsgBox prompt:="Arg1 is   " & Nmbr
     Let Nmbr = 999
    End Sub
    Sub InLisWbFirstWsCodeModuleMultipleArguments(ByVal Nmbr As Long, ByVal NuverNmbr As Long)
     MsgBox prompt:="Arg1 is  " & Nmbr & ", Arg2 is  " & NuverNmbr
    End Sub
    

    Closed workbook - UverFile.xls : https://app.box.com/s/u7r2jw79m8ou70otn7xcxced2qkot4w4

    Module "Modul1" in UverFile.xls
    Code:
    Option Explicit
    Private Sub MacroInUverFile(ByVal Nmbr As Long)
     MsgBox prompt:="Arg1 is   " & Nmbr
    End Sub
    Sub MacroUnderMacroInUverFile(ByVal Nmbr As Long, ByVal NuverNmbr As Long)
     MsgBox prompt:="Arg1 is  " & Nmbr & ", Arg2 is  " & NuverNmbr
    End Sub
    Worksheets Class module of first worksheet "Tabelle1" in UverFile.xls

    Code:
    Option Explicit
    Sub InUverFileFirstWsCodeModule(ByVal Nmbr As Long)
     MsgBox prompt:="Arg1 is   " & Nmbr
    End Sub
    Sub InUverFileFirstWsCodeModuleMultipleArguments(ByVal Nmbr As Long, ByVal NuverNmbr As Long)
     MsgBox prompt:="Arg1 is  " & Nmbr & ", Arg2 is  " & NuverNmbr
    End Sub
    



    I have tried to give a good spread of working examples, which I found useful to then use as a template to modify to exactly my needs.


    Here is the explanation to how things work , which makes the syntax more understandable:

    First the nested '
    This is generally how VBA handles making any spaces be taken as literal spaces, ( rather than , for example, mistaking them as separating arguments). You will see that in the codes, as I have posted I have done some exaggerated spaces in all code lines which helps to split up
    _ the LHS , which in a simplified / shortened use would be typically be left out
    and
    _ the RHS , most of which is always needed . (Most likely are likely typically to see the macro name and the arguments . The extra module code name allows you to use macros in any modules , ( regardless of if they are ] Private or Pubic )

    Just to make that clear, I have some exaggerated spaces in the code windows above either side of one of the `&`s , so pseudo I have
    Code:
            "---------LHS-------------"       &         "---------RHS------------------"
    or like, pseudo
    Code:
            "String bit containing full path and file name what you mostly don't use"            &          "String bit containing the macro name and the arguments like you more typically see"
    Those exaggerated extra spaces will vanish if you copy and paste that code into the VB editor code window. If I add spaces within the path string on the LHS, such as changing a file name from UverFile.xls to Uver File.xls , then as perhaps expected, the spaces will not change. This is because the enclosing ' ' is doing its job of ensuring that all is taken as literally as it is given.

    On the RHS we need also that the information is taken exactly as we give it. This needs to be stored into a buffer from when it is then retrieved and pseudo physically put in. This is why I can add some rogue spaces, as I have done in the code section named ' mess about with argument positions. This modification is also not changed when you post into the VB Code window. This helps us to understand the nested " "

    the nested " " in the variable arguments bit.

    This is much less difficult then a lot of literature suggests. The only time you need those enclosing quote pair is if you are giving string values in the argument. That is generally the case in VBA code lines, the enclosing quote indicating that a string is being given. ( Since you are already inside a string, then the double quotes need to be doubled, as is standard VBA syntax).
    If you are using variables, rather than hard coding, you never need this following often seen complicated syntax, ( provided you have your variables at the top of a module, outside any subroutine ). What I am saying is, that the following complicated argument syntax is, in most cases, more complicated than needed

    """ & Arg1 & """ , """ & Arg2 & """


    In most cases, that complicated form above can be reduced to this sort of form below

    Arg1 , Arg2

    To use that simplified form, the variables must be outside the macro with the scheduling Application.OnTime code line, and it must be at the top of the code module, or else, the scheduled macro which is to be set off by VBA later , won't know where to get the variables from

    So do not really "need" that complicated syntax, provided you use "module level" variables. But if you use that complicated syntax, it will have the effect of placing the value from the variable in the final argument string that VBA puts into the code line it write to run the scheduled macro later. This would have the effect of that if you use that syntax, and your variables are local, then you might be fooled into thinking that you , ( that is to say VBA in the scheduled macro later ), are using the variables. In fact you are hard coding with values into the string that will finally be used by VBA later in the scheduled macro. I suppose you might say that is using variables within the calling macro, at least from the practical point of use. But understanding what is actually going on, helps , I think, to see where the sometime daunting syntax comes from.

    In my demo macros, I refer to that way of using the calling macro variables as "Pseudo" variables use.

    Further more, the point that Nick P was making in his answer, is that 4 of those quotes around each variable in that very complicated argument syntax, are there to give the typical required finally seen double enclosing " " pair around a string value. If one of those variables in the example, for example Arg2 , is a number, then even for the case of using the "trick" to make it appear that you are using variable within the scheduling macro, you can do away with some of those quotes, in particular the ones giving finally seen by VBA the the enclosing " " pair, reducing it to

    """ & Arg1 & """ , " & Arg2 & "




    Examining the right hand side syntax for macro name and arguments.

    In all the coding I have a Debug.Print after each Application.OnTime code line. What this is showing is the actual RHS part of the string that VBA uses later when running the scheduled macro. So that is showing the part containing the macro name and the arguments. This helps to show the main point I am trying to get across.

    For example, the string in what I refer to as the "Pseudo" variables use , looks like this:

    !'Modul1.DoubleCheck "465.42" , "25.4" '

    Or, as noted, if a variable, for example, the second is a number , then you can also use this

    !'Modul1.DoubleCheck "465.42" , 25.4 '



    For what I call the 'Real variable use , the string "seen" must actually use the variable names

    !'Modul1.DoubleCheck Modul1.Pbic_Arg1 , Pbic_Arg2 '


    Just to clarify that Last code line above. The sub routine being scheduled is Sub DoubleCheck( ) which I have located in my code module with the code name Modul1

    Also in that same code module are placed at the top of the module , declarations for the variable, Pbic_Arg1 and Pbic_Arg2 . Pbic_Arg1 is Private , and Pbic_Arg2 is Publc


    If you try my coding out running from the VB Editor in step ( F8 ) mode , whilst you have the Immediate Window open , then I think that will help make everything clear


    Summary
    See next post







    Last edited by DocAElstein; 01-20-2020 at 08:20 PM.
    A Folk, A Forum, A Fuhrer ….

  2. #12
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,458
    Rep Power
    10

    Summary


    At the end of the day, the key to getting the syntax correct , and to understanding it , is as follows: You must arrange it such that what VBA "has", ( which you can check via a Debug.Print of the string you are giving ) needs to have a similar form to how you might manually write in arguments in a code line to call a sub routine taking in arguments. You can add a few extra spaces between multiple arguments and the separating comer , just as you might do carelessly when typing in manually a series of arguments. Presumably, VBA later, when it uses exactly your given string, it does something similar to what happens when you physically write or paste such things in, the result of which is that those extra spaces get removed.

    The point of the enclosing ' ' is to indicate to VBA to take literally exactly as you have written it. In my explicit code lines we need that for both the LHS and the RHS. More typically the LHS is omitted.

    Any use of a complicated combination of many double or triple " pairs is more of a trick to give you a way to effectively use variables that are within the scheduling macro , in the scheduling Application.OnTime code line. If your variables are in a code module outside of any sub routine, then the variable syntax is much simplified. In this case you do not actually need any quotes within the main string, not even if the a variable type is string. ( The complete second argument of the Application.OnTime always needs to be enclosed in a quote pair )


    Alan


    Ref
    https://groups.google.com/forum/?hl=...o/4rf3VBejtU0J
    https://www.mrexcel.com/board/thread...24/#post398494
    http://markrowlinson.co.uk/articles.php?id=10
    http://www.tushar-mehta.com/publish_...n_method.shtml

    P.S.
    @ Holger Leichsenring - Hi . I think the apostrophes must enclose the macro name AND the arguments. Any number types can be passed without quotes. The macro you want to call can reside in any module, in any workbook, (open or closed) , and need not be Public. ( My geuss is that `Application.OnTime` uses the same wiring as `Application.Run` , which has the advantage, over simple Calling a sub , that it will run both Public and Private subs ( https://stackoverflow.com/questions/...09370#59809370 ) )

    Gruß, Alan




    Last edited by DocAElstein; 01-20-2020 at 08:21 PM.
    A Folk, A Forum, A Fuhrer ….

  3. #13
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,458
    Rep Power
    10
    This is the sort of output seen in the Immediate window, which is showing the right hand side of the Application.OnTime second argument string




    Code:
    Rem 1
    This workbook module, single arrgument
    !'Modul1.UnderMainMacro 465'
    !'Modul1.UnderMainMacro "465"'
    
    UverFile module, single argument
    !'Modul1.MacroInUverFile 465'
    !'Modul1.MacroInUverFile "465"'
    
    Thisworkbook module, multiple arguments
    !'Modul1.UnderUnderMainMacro 465, 25'
    !'Modul1.UnderUnderMainMacro 465, "25"' 
    
    UverFile module, multiple argument
    !'Modul1.MacroUnderMacroInUverFile 465, 25'
    !'Modul1.MacroUndermacroInUverFile 465, "25"'
    
    mess about with argument positions
    !'Modul1.UnderUnderMainMacro      465   ,     "25"          '
    
    This workbook first worksheet code module, single arrgument
    !'Tabelle1.InLisWbFirstWcCodeModule 465'
    !'Tabelle1.InLisWbFirstWcCodeModule "465"'
    
    UverFile  first worksheet code module, single arrgument
    !'Tabelle1.InUverFileFirstWsCodeModule 465'
    !'Tabelle1.InUverFileFirstWsCodeModule "465"'
    
    This workbook first worksheet code module, multiple arguments
    !'Tabelle1.InLisWbFirstWcCodeModuleMultipleArguments 465      ,  "25"         '
    !'Tabelle1.InLisWbFirstWcCodeModuleMultipleArguments      "465"   ,   25    '
    
    UverFile  first worksheet code module, Multiple  arrgument
    !'Tabelle1.InUverFileFirstWsCodeModuleMultipleArguments   465   ,    "25"       '
    !'Tabelle1.InUverFileFirstWsCodeModuleMultipleArguments "465"   ,    "25"  '
    
    Doubles do not have to be in quotes either  ' This workbook module, double argument arrgument
    !'Modul1.DoubleCheck 465.5   , "25.4"    '
    
    Rem 2 Variables
    '2a)  "Pseudo"  variables use
    !'Modul1.DoubleCheck  "465.42"  ,   "25.4"  '
    !'Modul1.DoubleCheck  "465.42"  ,   25.4  '
    
    '2b) Real varable use
    !'Modul1.DoubleCheck  Modul1.Pbic_Arg1  ,   Pbic_Arg2  '
    !'Modul1.DoubleCheck Modul1.Pbic_Arg1, Pbic_Arg2'
    !'Modul1.DoubleCheck module2.Pbic_Arg1, Pbic_Arg2'
    
    
    
    Rem 3     ByRef Check
    25.4
    
    
    
    Rem 3     ByRef Check
    25.4
    
    
    
    Rem 3     ByRef Check
    999.99
    Last edited by DocAElstein; 01-20-2020 at 09:06 PM.
    A Folk, A Forum, A Fuhrer ….

  4. #14
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,458
    Rep Power
    10

    Grid coordinates for a Range using [ ] & Evaluate(" ") through a Named Range. Code 2

    Second Code with further lines to overcome extra () required for start row and star column codes


    Obtaining grid coordinates for an Area of contiguous cells in a Spreadsheet using [ ] and Evaluate(" ") through the use of a Named Range for that Area

    Aka ' It is a Range Name Test 2: Its n Range Name Test 2: 's 'n Rng Name Test 2: s n Rg Name Testie 2: snRg.Name = "snRgNme"
    This code is in support of other Posts in various Threads. ( I will edit the Links as I reference this post )




    The code takes in a hard coded Range, A1:E10.
    That Range is given a Name as held in the Names Register of a Workbook ( Workbooks Scope ).
    Various code lines are developed which reference this Named Range and return the Grid Coordinates.

    These coordinates are held within the following Long Type Variables
    Cs is the column count
    sClm is the start column
    stpClm is the stop column
    Rs is the rows count start row
    sRw is the start row
    stpRw is the stop row

    Code:
    ' Code 2
    '10   ' It is a Range Name Test 2: Its n Range Name Test 2: 's 'n Rng Name Test 2: s n Rg Name Testie 2: snRg.Name = "snRgNme"
    Sub snRgNameTest2()  ' Inspired by..   snb     .. " array [     ] "       '  http://www.excelfox.com/forum/showthread.php/2083-Delete-One-Row-From-A-2D-Variant-Array?p=9714#post9714
    20    ' Worksheets Info
    30    Dim ws As Worksheet '                                      ' Preparing a "Pointer" to an Initial "Blue Print" ( or a Form, or a Questionnaire not yet filled in, a template   etc.) in Memory of the Object ( Pigeon Hole with a bit of paper or code lines on that can be filled in to refer to a specific Object of this type ) . This also us to get easily at the Methods and Properties through the applying of a period ( .Dot) ( intellisense )
    40    'Set ws = ThisWorkbook.Worksheets("NPueyoGyanArraySlicing") 'The worksheets collection object is used to Set ws to the Sheet we are playing with, so that we carefull allways referrence this so as not to go astray through Excel Guessing inplicitly not the one we want...              ' Values are filled at the memory locations and the directions there are specified in the variable "Blue Print "Pointer". In this case a Filled in Blue Print is passed.      http://www.excelforum.com/excel-programming-vba-macros/1138804-help-understanding-class-instancing-cant-set-ws-new-worksheet-intellisense-offers-it-4.html#post4387191
    50    Set ws = ActiveSheet ' Alternative to last line, make code apply to the current active sheet, - That being "looked at" when running this code        '
    60    Dim vTemp As Variant ' To help development when you are not sure what type is retuned. "Suck and see what comnes out!"  Highlight it and Hit Shift+F9 to see it in the imediate Window
    70    ' Named Range referrencing ' Workbooks ( Default ) Scope                                                                                                                                      Invoke  Pike  Evaluate Rabbit Rabbit. How's the Bunny ? Bunnytations Banters
    80    Dim snRg As Range: Set snRg = ws.Range("A1:E10")
    90    Dim sName As String: Let sName = "snRgNme" '
    100   Let snRg.Name = "snRgNme"  ' It is a Range Name me  - " 's 'n Range Name me "  ..  "snRgNme"  ;)  This name appears permanentlly in then sheet. It remains referrencing this range unless the name iis deleted or the range referrenced is overwritten by a similar code line which has a different range in it on RHS of =                                                                                                  http://www.thespreadsheetguru.com/blog/2014/6/20/the-vba-guide-to-listobject-excel-tables
    110   Let snRg.Name = sName      ' Identical to last line
    120
    130    '== DANGER: === Pitful: Above we gave the Range Object a Name, but now see what  "Name"  or  "Name" 's  comes back "!"  !
    131  Dim clms() As Variant 'Array to take returned Variant type Field of sequential column numbers
    132     Dim retRefstrName As String, retObjName As Object
    133     Let retRefstrName = snRg.Name: Set retObjName = snRg.Name: Debug.Print snRg.Name 'something of the form   "NPueyoGyanArraySlicing!$A$1:$E$10" is reveald in Immediate ( Ctrl+G when in VB Editor ) Window
    134     'Let clms() = Evaluate("column(=NPueyoGyanArraySlicing!$A$1:$E$10)") 'Let clms() = Evaluate("column(" & retRefstrName & ")")' Rintime Error 13: Incompatiblee types
    135     Let clms() = Evaluate("column(NPueyoGyanArraySlicing!$A$1:$E$10)") 'Works
    137     Dim NameOnly As String: Let NameOnly = Replace((snRg.Name), "!", "", (InStr(1, (snRg.Name), "!"))):  'Debug.Print snRg.Name: Dim pos&: pos = InStr(1, (snRg.Name), "!"): NameOnly = Replace((snRg.Name), "!", "", pos) ' We had  ----  "NPueyoGyanArraySlicing!$A$1:$E$10" This is a String referrece returned when the Name Object is used directly or set to a String Variable.     so here I return a string that starts at the position of the ! and which replaces in that truncated shortened string -  "!$A$1:$E$10"   the "!" with nothing
    138     Let clms() = Evaluate("column(" & NameOnly & ")"): Let clms() = Evaluate("column(" & Replace((snRg.Name), "!", "", (InStr(1, (snRg.Name), "!"))) & ")")
    139
    140     Dim strName As String: Let strName = snRg.Name.Name: Debug.Print strName: Let strName = retObjName.Name: Debug.Print strName ' returns our original "CoN"
    142     Let clms() = Evaluate("column(" & strName & ")")
    150     Dim rngF1G2 As Range: Set rngF1G2 = Range("F1:G2"): Let Range("F1:G2").Value = "From Line 150"
    151     Let Range("=NPueyoGyanArraySlicing!F1:G2").Value = "From Line 151"
    152     Let rngF1G2.Name = "snFG": Let Range("snFG").Value = "From Line 152"
    153
    154
    159    '===============
    160   Let clms() = Evaluate("column(snRgNme)"): Let clms() = [column(snRgNme)] ' Full and "shorthand" Simple 1 D "pseudo horizontal" Array of column Indicies.
    170  '
    180   ' Count, Start, and Stop of columns in an Area of contiguous cells in a Spreadsheet
    190   Dim Cs As Long 'Variable for ColumnsCount.             -This makes a Pigeon Hole sufficient in construction to house a piece of Paper with code text giving the relevant information for the particular Variable Type. VBA is sent to it when it passes it. In a Routine it may be given a particular "Value", or ("Values" for Objects).  There instructions say then how to do that and handle(store) that(those). At Dim the created Paper is like a Blue Print that has some empty spaces not yet filled in. Long is very simple to handle, final memory "size" type is known (13.456, 00.001 have same "size" computer memory ),so an Address suggestion can be given for when the variable is filled in. (Long is a Big whole Number limit (-2,147,483,648 to 2,147,483,647). If you need some sort of validation the value should only be within the range of a Byte/Integer otherwise there's no point using anything but Long.-upon/after 32-bit, Integers (Short) need converted internally anyway, so a Long is actually faster)
    200   Let Cs = Evaluate("columns(snRgNme)") ' = 5
    210   'Let Cs = Evaluate("columns(RetunedsnRgName)") 'Run time Error as expected
    220   Let Cs = [columns(snRgNme)]           ' = 5              'Is this Most Powerful Command in VBA?, or what ...    http://www.ozgrid.com/forum/showthread.php?t=52372       http://www.mrexcel.com/forum/excel-questions/899117-visual-basic-applications-range-a1-a5-vs-%5Ba1-a5%5D-benefits-dangers.html
    230   'Let Cs = [columns(RetunedsnRgName)]           'Run time Error as expected
    240   Let Cs = [columns(A1:E10)]             ' = 5
    250                                                               Let vTemp = Evaluate("column(snRgNme)") ' Reveals an Array {1, 2, 3, 4, 5}  -  1 Dimension "pseudo Horizontal" Array
    260   Dim sClm As Long 'Variable for Start Column
    270   Let sClm = Evaluate("column(A1:E10)")(1)
    280   Let sClm = Evaluate("column(snRgNme)")(1) ' = 1
    290   Let sClm = [column(A1:E10)]()(1)
    300   Let sClm = [column(snRgNme)]()(1)
    301
    302   Let sClm = Evaluate("=MIN(column(snRgNme))"): Let sClm = [=MIN(column(snRgNme))] 'Alternative using Spreadsheet Functions to avoid having to VBA ()(  ) after the Evaluate
    329   '
    330   Dim stpClm% ' Variable for Stop column Number               '  ( % is shorthand for As Long ..http://www.excelforum.com/showthread.php?t=1116127&p=4256569#post4256569
    340   Let stpClm = sClm + (Cs - 1)             ' = 5
    350   ' [ ]
    360   Let stpClm = [column(A1:E10)]()(1) + ([columns(A1:E10)] - 1)
    370   Let stpClm = [column(snRgNme)]()(1) + ([columns(snRgNme)] - 1)
    380   ' In between step [ ] and Evaluate(" ")
    390   Let stpClm = [column(snRgNme)]()(UBound([column(snRgNme)]))
    400   ' Now Full Evaluate(" ")
    410   Let stpClm = Evaluate("column(snRgNme)")(1) + (Evaluate("columns(snRgNme)") - 1)
    420   Let stpClm = Evaluate("column(snRgNme)")(UBound(Evaluate("column(snRgNme)")))
    421
    430   Let stpClm = Evaluate("=MIN(column(snRgNme))") + (Evaluate("columns(snRgNme)") - 1) ''Alternatives using Spreadsheet Functions to avoid having to VBA ()(  ) after the Evaluate
    431   Let stpClm = [=MIN(column(snRgNme))] + ([columns(snRgNme)] - 1)
    432   Let stpClm = [=MIN(column(snRgNme)) + (columns(snRgNme) - 1)]
    439  '
    440   ' Start, Count and Stop of rows in an Area of contiguous cells in a Spreadsheet
    450   Dim Rs As Long 'Rows Count
    460   Let Rs = Evaluate("rows(snRgNme)")
    470   Let Rs = [rows(snRgNme)]
    480   Let Rs = [rows(A1:E10)]
    490                                                               Let vTemp = Evaluate("row(snRgNme)") ' = {1; 2; 3; 4; 5; 6; 7; 8; 9; 10}
    500   Dim sRw As Long 'Start Row
    510   Let sRw = Evaluate("row(A1:E10)")(1, 1) 'Note a 2 Dimensional,  1 column, "vertical" Array is returned : ' vTemp = {1; 2; 3; 4; 5; 6; 7; 8; 9; 10}
    520   Let sRw = Evaluate("row(snRgNme)")(1, 1)
    530   Let sRw = [row(A1:E10)]()(1, 1)
    540   Let sRw = [row(snRgNme)]()(1, 1)
    541
    550   Let sRw = Evaluate("=MIN(Row(snRgNme))"): Let sRw = [=MIN(Row(snRgNme))] '''Alternatives using Spreadsheet Functions to avoid having to VBA ()(  ) after the Evaluate
    560
    570   Dim stpRw% 'Stop Row
    580   Let stpRw = sRw + (Rs - 1)
    590   Let stpRw = [row(A1:E10)]()(1, 1) + ([rows(A1:E10)] - 1)
    600   Let stpRw = [row(snRgNme)]()(1, 1) + ([rows(snRgNme)] - 1)
    610  '
    620   Let stpRw = [row(snRgNme)]()(UBound([row(snRgNme)], 1), 1) 'UBound([row(snRgNme)], 1) is Ubound first ( "row" ) dimension.  UBound([row(snRgNme)], 2) would be the second dimension ( "column" ) count
    630  '
    640   Let stpRw = Evaluate("row(snRgNme)")(1, 1) + (Evaluate("rows(snRgNme)") - 1)
    650   Let stpRw = Evaluate("row(snRgNme)")(UBound(Evaluate("row(snRgNme)")), 1)
    660  '
    670   Let stpRw = Evaluate("=MIN(Row(snRgNme))") + (Evaluate("rows(snRgNme)") - 1) ''''Alternatives using Spreadsheet Functions to avoid having to VBA ()(  ) after the Evaluate
    680   Let stpRw = [=MIN(Row(snRgNme))] + [rows(snRgNme)] - 1
    690   Let stpRw = [=MIN(Row(snRgNme))] + [rows(snRgNme)] - 1
    700   Let stpRw = [=MIN(Row(snRgNme)) + rows(snRgNme) - 1]
    End Sub
    A Folk, A Forum, A Fuhrer ….

  5. #15
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,458
    Rep Power
    10

    Alternative Codes using [ ] shorthand

    Alternative Codes using [ ] shorthand
    Delete One Row From A 2D Excel Range Area

    ' To Test Function, Type some arbitrary values in range A1:E10, step through Main Test Code in F8 Debug Mode in VB Editor, and examine Worksheet, Immediate Window ( Ctrl+G when in VB Editor ), hover over variables in the VB Editor Window with mouse cursor, set watches on variables ( Highlight any occurrence of a variable in the VB Editor and Hit Shift+F9 ) , etc.. and then you should expected the required Output to be pasted out starting Top Left at cell M17


    Code:
    ' Delete One Row From A 2D Excel Range Area
    ' To Test Function, Type some arbitrary values in range A1:E10, step through code in F8 Debug Mode in VB Editor, and examine Worksheet, Immediate Window ( Ctrl+G when in VB Editor ), hover over variables in the VB Editor Window with mouse cursor, set watches on variables ( Highlight  any occurrence of a variable in the VB Editor and Hit Shift+F9 ) , etc.. and then you should expected the required Output to be pasted out starting Top Left at cell M17
    ' "Short hand", ShtHd, version using []
    '  requires snb and kalak "neat trick" so you can to all intents and purpose do very close to doing vba Un Hard coded in [ ] -    http://www.excelfox.com/forum/showthread.php/2083-Delete-One-Row-From-A-2D-Variant-Array?p=9714#post9714       http://www.mrexcel.com/forum/excel-questions/899117-visual-basic-applications-range-a1-a5-vs-%5Ba1-a5%5D-benefits-dangers.html#post4331217
    '  and    Evaluate [ ]  Properties , AloPerties, Methods - Alan Dynamic Coding Wonks    http://www.excelforum.com/excel-programming-vba-macros/1141369-evaluate-and-differences-evaluated-array-return-needs-extra-bracket-for.html#post4400666
    Function FuR_AlanShtHd(ByVal rngIn As Range, ByVal FoutRw As Long) As Variant
    1   Let rngIn.Name = "snRgNme"
    5   Dim vTemp As Variant 'A varyable to fill with something and "suck and see" what you get
    10  ' use "neat magic" code line    arrOut() = Application.Index(arrIn(), rwsT(), clms())  '                 http://www.excelforum.com/excel-new-...ba-arrays.html                      http://www.mrexcel.com/forum/excel-q...ml#post4375354
    20  ' BUT in Cells form             arrOut() = Application.Index(Cells, rwsT(), clms())    '                      http://www.excelforum.com/excel-prog...t-range-2.html
    30  Dim ws As Worksheet '                                      ' Preparing a "Pointer" to an Initial "Blue Print" ( or a Form, or a Questionnaire not yet filled in, a template   etc.) in Memory of the Object ( Pigeon Hole with a bit of paper or code lines on that can be filled in to refer to a specific Object of this type ) . This also us to get easily at the Methods and Properties through the applying of a period ( .Dot) ( intellisense )
    40  Set ws = rngIn.Parent                                      ' Values are filled at the memory locations and the directions there are specified in the variable "Blue Print "Pointer". In this case a Filled in Blue Print is passed.      http://www.excelforum.com/excel-prog...ml#post4387191
    50                                ws.Range("K30").ClearContents: ws.Range("K30").Value = "Here I am, in this Worksheet!"
    60  'clms()
    70  Dim sClm As Long, Cs As Long 'Variable for Count of, Start Column. - This makes a Pigeon Hole sufficient in construction to house a piece of Paper with code text giving the relevant information for the particular Variable Type. VBA is sent to it when it passes it. In a Routine it may be given a particular "Value", or ("Values" for Objects).  There instructions say then how to do that and handle(store) that(those). At Dim the created Paper is like a Blue Print that has some empty spaces not yet filled in. Long is very simple to handle, final memory "size" type is known (13.456, 00.001 have same "size" computer memory ),so an Address suggestion can be given for when the variable is filled in. (Long is a Big whole Number limit (-2,147,483,648 to 2,147,483,647). If you need some sort of validation the value should only be within the range of a Byte/Integer otherwise there's no point using anything but Long.-upon/after 32-bit, Integers (Short) need converted internally anyway, so a Long is actually faster)
    80  Let sClm = [=MIN(column(snRgNme))] '###Not needed now. Alternative using Spreadsheet Functions to avoid having to VBA ()(  ) after the Evaluate
    90  Dim clms() As Variant '           Evaluate Function used below returns a Field of Variant Element Types so the Array Elemments must be Declared appropriately. Must be adynamic Array to accept and be effectivelly sized by the Field size assigned to it.
    95  Let clms() = [column(snRgNme)] '  snb  Range Name equivalent so ###                                                           'Let clms() = Evaluate("column(" & CL(sClm) & ":" & CL(sClm + (Cs - 1)) & ")")
    100
    160 'rwsT()
    170 Dim sRw As Long, Rs As Long, stpRw As Long '
    180  Let sRw = [=MIN(Row(snRgNme))] '''Alternatives using Spreadsheet Functions to avoid having to VBA ()(  ) after the Evaluate '         Let sRw = rngIn.Areas.Item(1).Row
    190  Let Rs = [rows(snRgNme)]          'Let Rs = rngIn.Areas.Item(1).Rows.Count
    191  Let stpRw = [=MIN(Row(snRgNme)) + rows(snRgNme) - 1] '''Alternatives using Spreadsheet Functions to avoid having to VBA ()(  ) after the Evaluate
    200
    240 'Get Full row indicies convenientally ( As 1 D "pseudo horizontal" Array ) from Spreadsheet Column() Function
    250 Dim rws() As Variant: Let rws() = Evaluate("column(" & CL(sRw) & ":" & CL(sRw + (Rs - 1)) & ")")
    251  Let vTemp = [CL(1)]: vTemp = [CL(MIN(Row(snRgNme)))] 'Both Return "A"
    252  vTemp = [CL(MIN(Row(snRgNme)) + rows(snRgNme) - 1)] 'Returns "J"
    254  Let rws() = [column(A:J)] ' Works
    257  'Let rws() = [column(CL(1):J)] ' Fails - Bug in Excel ! ? !
    258  'Let rws() = [column(CL(MIN(Row(snRgNme))):CL(MIN(Row(snRgNme)) + rows(snRgNme) - 1))] ' Fails - Bug in Excel ! ? !
    260  Let rws() = Evaluate("column(" & [CL(MIN(Row(snRgNme)))] & ":" & [CL(MIN(Row(snRgNme)) + rows(snRgNme) - 1)] & ")")
    270
    280 'Get full sequential row indicies in a string.
    290 Dim strRws As String: Let strRws = VBA.Strings$.Join(rws(), "|") '            'The VBA strings collection such as Join in there basic form must not returnn a string, they can also return for example Null, a special type of variant. That lies within it's "powers. - It will coerce even an Empty, or Null to a variant type and return that. That takes extra ( unecerssary work here ). If the result of a function is used as a string or assigned it to a string variable, use the $ form of the function. This results in faster executing code, because a conversion from a variant to a string is unnecessary.      http://www.excelforum.com/excel-new-...ml#post4084783      I believe that without $ a Strings collection Function coerces the first parameter into  Variant, with $ does not - that's why $ is preferable over no $ , it's theoretically more efficient.        http://www.xoc.net/standards/rvbacc....rSignFunctions
    300
    330 'Get String with missing row
    340 Dim strrwsD As String: Let strrwsD = Replace(strRws, "|" & FoutRw & "", "", 1, -1)
    350
    360 'Get Array ( 1 D Pseudo Horizontal ) of required row indicies
    370 Dim rwsS() As String '              The VBA Strings Collection Function, Split, used below returns a Field of String Element Types so the Array Elemments must be Declared appropriately. It must be adynamic Array to accept and be effectivelly sized by the Field size assigned to it.
    375 Let rwsS() = VBA.Strings$.Split(strrwsD, "|", -1)
    380 'final Transposed Array for "magic neat" code line
    390 Dim rwsT() As String: ReDim rwsT(0 To (UBound(rwsS())), 1 To 1) '          Both the type and size of Array is known so can be decared initially appropriatelly. Re Dim must be used as Dim only takes values, not variables
    400 Dim Cnt As Long
    410     For Cnt = 0 To UBound(rwsS())
    420      Let rwsT(Cnt, 1) = rwsS(Cnt)
    430     Next Cnt
    
    440 'Output Array
    450 Dim arrOut() As Variant
    460 Let arrOut() = Application.Index(ws.Cells, rwsT(), clms()) '"Magic neat" Code line in Cells first argument Form
    470
    480 Let FuR_AlanShtHd = arrOut()
    490
    500 ' . Transpose
    510 Dim rwsDotT() As Variant '         Transpose Function used below returns a Field of Variant Element Types so the Array Elemments must be Declared appropriately. Must be adynamic Array to accept and be effectivelly sized by the Field size assigned to it.
    520 Let rwsDotT() = Application.Transpose(rwsS())
    530 Let arrOut() = Application.Index(ws.Cells, rwsDotT(), clms())
    540
    550 Let FuR_AlanShtHd = arrOut()
    '
    End Function
    A Folk, A Forum, A Fuhrer ….

  6. #16
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,458
    Rep Power
    10
    More Named Range Scope Wonks. Problems when Worksheet Scoped WorkSheet is different from Worksheet refered to in RefersTo:= Range Object argument



    Here is a another partial solution to the This Thread
    http://www.excelforum.com/excel-prog...acket-for.html

    It was also used to answer a few questions I had here:
    http://www.thespreadsheetguru.com/bl...o-named-ranges[I][COLOR="#000080"] ( Comment 22 )
    Here is what I wrote there:
    Reply Posted at
    http://www.thespreadsheetguru.com/bl...o-named-ranges
    6 th June 2016:

    Hi
    Hi Just feeding back from my "experiments" over the weekend_...
    http://www.excelforum.com/showthread...t=#post4404276
    _..So now o answer my questions:
    _1) I have not yet seen anything to suggest the answer to that is not yes.
    A Folk, A Forum, A Fuhrer ….

  7. #17
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,458
    Rep Power
    10

    Array List Sort of Referrences

    Referrences in suppost of this post:
    http://www.excelfox.com/forum/showth...=9985#post9985

    and solution to this post
    http://www.excelforum.com/excel-prog...ml#post4507157



    ' http://www.snb-vba.eu/VBA_Arraylist_en.html
    ' http://www.snb-vba.eu/VBA_Arraylist_en.html#L_11.3



    ' https://usefulgyaan.wordpress.com/20...1/#comment-587

    ' https://usefulgyaan.wordpress.com/20...1/#comment-515




    Code:
    '   https://usefulgyaan.wordpress.com/2013/06/12/vba-trick-of-the-week-slicing-an-array-without-loop-application-index/comment-page-1/#comment-587
    Sub M_snbSortof()  '   http://www.snb-vba.eu/VBA_Arraylist_en.html#L_11.3
    Dim rngVoll As Range: Set rngVoll = Tabelle3.Range("A1:E10")
    Dim snAll() As Variant, Sported() As Variant
     Let snAll() = rngVoll.Value
    Dim j As Long, jj As Long
        With CreateObject("System.Collections.Arraylist")
            For j = 1 To UBound(snAll(), 1)
             .Add snAll(j, 3)
            Next
         .Sort
         Let Sported() = .ToArray
         .Clear
            For j = 0 To UBound(Sported())
                For jj = 1 To UBound(snAll(), 1)
                    If snAll(jj, 3) = Sported(j) Then
                    ' Use Range to overcome  Array size Limits of Worksheets Functions
                    'Dim Clm As Range: Set Clm = Application.Index(rngVoll, jj, 0)
                    ' .Add Clm.Value
                    ' .Add (Application.Index(rngVoll, jj, 0).Value)
                    
                    ' Use Cells to overcome  Array size Limits of Worksheets Functions
                    Dim LB As Long, UB As Long '…User Given start and Stop Column as a Number
                     Let LB = LBound(snAll(), 2): Let UB = UBound(snAll(), 2)
                    Dim strLtrLB As String, strLtrUB As String '…Column Letter corresponding to Column Number
                    'There are many ways to get a Column Letter from a Column Number – excelforum.com/tips-and-tutorials/1108643-vba-column-letter-from-column-number-explained.html
                     Let strLtrLB = Split(Cells(1, LB).Address, "$")(1) 'An Address Method
                     Let strLtrUB = Replace (Replace(Cells(1, UB).Address, "1", ""), "$", "") 'A Replace Method
                    'Obtain Column Indicies using Spreadsheet Function Column via VBA Evaluate Method
                    Dim clms() As Variant
                     Let clms() = Evaluate("column(" & strLtrLB & ":" & strLtrUB & ")") 'Returns 1 D “pseudo” Horizontal Array of sequential numbers from column number of LB to UB
                    'Or
                     clms() = Evaluate("column(" & Split(Cells(1, LB).Address, "$")(1) & ":" & Replace (Replace(Cells(1, UB).Address, "1", ""), "$", "") & ")")
                    .Add (Application.Index(Tabelle3.Cells, jj, clms()))
                     
                     'Let snAll(jj, 3) = ""
                    Exit For
                    End If
                Next jj
            Next j
            For j = 0 To .Count - 1
             Tabelle3.Cells(j + 1 + 10, 1).Resize(, UBound(snAll, 2)) = .Item(j)
            Next j
        End With
    End Sub
    '
    Sub M_snb()
    Dim sn, sp, j As Long, jj As Long
    sn = Tabelle3.Range("A1:E10")
        With CreateObject("System.Collections.Arraylist")
            For j = 1 To UBound(sn)
            .Add sn(j, 3)
            Next
         .Sort
         sp = .ToArray
         .Clear
            For j = 0 To UBound(sp)
                For jj = 1 To UBound(sn)
                    If sn(jj, 3) = sp(j) Then
                     .Add Application.Index(sn, jj)
                     sn(jj, 3) = ""
                    Exit For
                    End If
                Next
            Next
            For j = 0 To .Count - 1
             Tabelle3.Cells((j + 1) + 10, 1).Resize(, UBound(sn, 2)) = .Item(j)
            Next
        End With
    End Sub
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    'Rem Ref
    '    http://www.excelforum.com/excel-programming-vba-macros/1139207-how-to-move-a-userform-and-module-from-one-book-to-another-2.html
    '    http://www.excelforum.com/excel-programming-vba-macros/1138300-vba-userform-value-check-if-user-form-buttons-checked-not-working-check-button-on-open.html
    '    http://www.excelforum.com/excel-programming-vba-macros/1139742-workbooks_open-crashes-when-file-opened-with-code-manually-open-ok-userform-issue.html
    '    http://www.excelfox.com/forum/showthread.php/2130-Sort-an-array-based-on-another-array-VBA?p=9985#post9985
    '    http://www.snb-vba.eu/VBA_Arraylist_en.html
    '    http://www.snb-vba.eu/VBA_Arraylist_en.html#L_11.3
    '    http://www.excelforum.com/showthread.php?t=1154829&page=4#post4502593
    '    http://www.excelforum.com/excel-programming-vba-macros/1160648-how-to-create-a-pop-up-notification-for-two-different-conditions-at-the-same-time.html#post4507157
    '    http://www.excelfox.com/forum/showthread.php/2130-Sort-an-array-based-on-another-array-VBA?p=9985#post9985



    http://www.excelforum.com/showthread...=4#post4502593
    A Folk, A Forum, A Fuhrer ….

  8. #18
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,458
    Rep Power
    10

    Code For Nelson

    Hi Nelson,
    I think both
    _ the ways to do this,
    _and the possibly output forms
    are infinite

    _ You must try to be a bit more precise in exactly what you want.

    _ I have done another fairly simple code:

    It is here:
    http://www.excelfox.com/forum/showth...0047#post10047

    It runs though all the Worksheets to calculate normal overtime and holiday overtime. The total added for all Worksheets is displayed in a message box:
    NelsonMessageBox.jpg http://imgur.com/XSvQpQi
    Attachment 1863




    I expect the code is not yet want you finally want. It tells you the total sum for Normal Overtime and Holiday overtime.
    ( I still do not understand what calculations should be done for total days )

    Please start a new Thread here: _.. http://www.excelfox.com/forum/forumd...p/2-Excel-Help

    _.. Please try again to explain exactly what you want.
    _.. I will then look at it again for you on Monday


    Alan

    Code:
    Code:
    ' An Initial code for Nelson for Post in this Forum    http://www.excelfox.com/forum/forumdisplay.php/2-Excel-Help
    Sub SomeingSumTotals()          '  https://www.dropbox.com/s/u76eo5trrtppgoi/SAMPLE2.xlsx?dl=0
    Rem 1) Worksheets info.
    Dim WsStear As Worksheet        ' Dim: For Object variabls: Address location to a "pointer". That has all the actual memory locations (addresses) of the various property values , and it holds all the instructions what / how to change them , should that be wanted later. That helped explain what occurs when passing an Object to a Call ed Fucntion or Sub Routine By Val ue. In such an occurance, VBA actually  passes a copy of the pointer.  So that has the effect of when you change things like properties on the local variable , then the changes are reflected in changes in the original object. (The copy pointer instructs how to change those values, at the actual address held in that pointer). That would normally be the sort of thing you would expect from passing by Ref erence.  But as that copy pointer "dies" after the called routine ends, then any changes to the Addresses of the Object Properties in the local variable will not be reflected in the original pointer. So you cannot actually change the pointer.)
                                    ' Set: Fill or partially Fill: Setting to a Class will involve the use of an extra New at this code line. I will then have an Object referred to as an instance of a Class. At this point I include information on my Pointer Pigeon hole for a distinct distinguishable usage of an Object of the Class. For the case of something such as a Workbook this instancing has already been done, and in addition some values are filled in specific memory locations which are also held as part of the information in the Pigeon Hole Pointer. We will have a different Pointer for each instance. In most excel versions we already have a few instances of Worksheets. Such instances Objects can be further used., - For this a Dim to the class will be necessary, but the New must be omitted at Set. I can assign as many variables that I wish to the same existing instance
    Rem 2) varables for some totals ;)
    Dim NOHrsV2 As Double, HOHrsV2 As Double, TDays As Long
     Let NOHrsV2 = 0: Let HOHrsV2 = 0: Let TDays = 0
    Rem 3) Loop through worksheets and give some Totals
    Dim Cnt As Long ' Loop Bound variable count for going through all worksheets
        For Cnt = 1 To ThisWorkbook.Worksheets.Count
         Set WsStear = ThisWorkbook.Worksheets.Item(Cnt)                   ' Set: Fill or partially Fill: Setting to a Class will involve the use of an extra New at this code line. I will then have an Object referred to as an instance of a Class. At this point I include information on my Pointer Pigeon hole for a distinct distinguishable usage of an Object of the Class. For the case of something such as a Workbook this instancing has already been done, and in addition some values are filled in specific memory locations which are also held as part of the information in the Pigeon Hole Pointer. We will have a different Pointer for each instance. In most excel versions we already have a few instances of Worksheets. Such instances Objects can be further used., - For this a Dim to the class will be necessary, but the New must be omitted at Set. I can assign as many variables that I wish to the same existing instance
        Dim lr As Long                                                     ' Long is very simple to handle, - final memory "size" type is known (123.456 and 000.001 have same "size" computer memory ) , and so a Address suggestion can be given for the next line when the variable is filled in.  '( Long is a Big whole Number limit (-2,147,483,648 to 2,147,483,647) If you need some sort of validation the value should only be within the range of a Byte/Integer otherwise there's no point using anything but Long.--upon/after 32-bit, Integers (Short) need converted internally anyways, so a Long is actually faster. )
         Let lr = WsStear.Range("E" & Rows.Count & "").End(xlUp).Row       ' The Range Object ( cell ) that is the last cell in the column of interest (CHOOSE a column typically that will always have a last Entry in any Data) ,( Row Number given by .Count Property applied to ( any Worksheet would do, so leaving unqualified is OK here, ) Spreadsheet Range Rows Property)    has the Property .End ( argument "Looking back up" ) appled to it. This Returns a new Range ( cell ) object which is that of the first Range ( cell ) with something in it "looking back up" in the XL spreadsheet from that last Cell. Then the .Row Property is applied to return a long number equal to the Row number of that cell:     Rows.Count is the very last row number in your Worksheet. It is different for earlier versions of Excel.  The End(xlUp) is the same as pressing a Ctrl+UpArrow key combination. The final ".Row" returns the row where the cursor stops after moving up.
        Dim FstDtaCel As Range: Set FstDtaCel = WsStear.Range("A2")        ' Worksheets Range(" ") Property used to return Range object of first cell in second row
        Dim arrInNorm() As Variant, arrInOver() As Variant                 ' In the next lines the .Value2 Property is applied a Range object which presents the the Value2 value or values in a single variable of appropriate type or a field of member Elements of varaint types.We are expecting the latter, so declare ( Dim ) a dynamic Array variable appropriately. It must be dynamic as its size will be defined at that assignment
         Let arrInNorm() = FstDtaCel.Offset(0, 8).Resize(lr - 1, 1).Value2 ' One thing you pick up when learning VBA programming is that referring to cells from one to another via an offset is both fundamental and efficient. That makes sense as Excel is all about using the offsets mentioned above. So like if you use them you can “cut out the middle man”. ( The middle man here might be considered as, for example, in VBA, using extra variables for different Range objects: A fundamental thing to do with any cell ( or strictly speaking the Range object associated to a cell ) is the Range Item Property of any range Object, through which you can “get at” any other Range object. http://www.excelforum.com/showthread.php?t=1154829&page=13&p=4563838&highlight=#post4563838 ( It is often quicker than using a separate variable for each Range object – probably as all the variable does is hold the offset , so you might as well use the offset in the first place.. ) )
         Let arrInOver() = FstDtaCel.Offset(0, 9).Resize(lr - 1, 1).Value2 ' Similarly Another thing you pick up along the way is that the cells ( or strictly speaking the Range objects associated with it ) can be organised into groups of cells which then are also called Range objects and are organised in their constituent parts exactly the same as for the single cell Range object. Once again this is all an indication of organising so that we get at information by sliding along a specific amount ( offset value). The Offset and Resize properties therefore return a new range object. I use the .Value 2 here as i seemed to get it for .Value anyway, not sure why yet, - so i thought be on the safe side , get it always and work somehow with that for now and convert as necerssary.
        Dim ShtCnt As Long ' Loop Bound Variable Count for hours columns looping
            For ShtCnt = 1 To UBound(arrInNorm(), 1) Step 1
                If arrInNorm(ShtCnt, 1) <> 0 And arrInOver(ShtCnt, 1) <> 0 Then Let NOHrsV2 = NOHrsV2 + arrInOver(ShtCnt, 1)
                If arrInNorm(ShtCnt, 1) = 0 And arrInOver(ShtCnt, 1) <> 0 Then Let HOHrsV2 = HOHrsV2 + arrInOver(ShtCnt, 1)
            Next ShtCnt
        Next Cnt
    Rem 4) Output some totals ;)
     MsgBox prompt:="Normal Overtime is " & NOHrsV2 * 24 & vbCrLf & "Holiday Overtime is" & HOHrsV2 * 24 ' NelsonMessageBox.jpg     http://imgur.com/XSvQpQi
    '4b) Tell you Totals                                                   ' Sub Speach() '                                        Richard Buttrey   http://www.excelforum.com/showthread.php?t=1164765&p=4535112#post4535112
    Dim Saps As Object
     Set Saps = CreateObject("SAPI.SpVoice")
     Saps.Speak "Hello Nelson. These are Sum totals for Normal Overtime and Holiday Overtime for the two Worksheets you gave.. Normal Overtime is " & NOHrsV2 * 24 & "..  Holiday Overtime is " & HOHrsV2 * 24 & ".. I expect this is not yet quite what you want."
    '                                                                      ' End Sub
    End Sub
    Attached Images Attached Images
    Attached Files Attached Files
    A Folk, A Forum, A Fuhrer ….

  9. #19
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,458
    Rep Power
    10
    Code for Nelson in this Thread
    http://www.excelfox.com/forum/showth...liday-overtime
    http://www.excelfox.com/forum/showth...0060#post10060

    Code:
    Option Explicit
    Sub IJAdjustTotalAllWorksheet()     '  http://www.excelfox.com/forum/showth...0060#post10060
    Rem 1) Workbooks Info.
    Dim Wb As Workbook                  ' Dim: For Object variabls: Address location to a "pointer". That has all the actual memory locations (addresses) of the various property values , and it holds all the instructions what / how to change them , should that be wanted later. That helped explain what occurs when passing an Object to a Call ed Fucntion or Sub Routine By Val ue. In such an occurance, VBA actually  passes a copy of the pointer.  So that has the effect of when you change things like properties on the local variable , then the changes are reflected in changes in the original object. (The copy pointer instructs how to change those values, at the actual address held in that pointer). That would normally be the sort of thing you would expect from passing by Ref erence.  But as that copy pointer "dies" after the called routine ends, then any changes to the Addresses of the Object Properties in the local variable will not be reflected in the original pointer. So you cannot actually change the pointer.)
     Set Wb = ActiveWorkbook            ' Set: Fill or partially Fill: Setting to a Class will involve the use of an extra New at this code line. I will then have an Object referred to as an instance of a Class. At this point I include information on my Pointer Pigeon hole for a distinct distinguishable usage of an Object of the Class. For the case of something such as a Workbook this instancing has already been done, and in addition some values are filled in specific memory locations which are also held as part of the information in the Pigeon Hole Pointer. We will have a different Pointer for each instance. In most excel versions we already have a few instances of Worksheets. Such instances Objects can be further used., - For this a Dim to the class will be necessary, but the New must be omitted at Set. I can assign as many variables that I wish to the same existing instance
    Dim wsStear As Worksheet            ' Used for each Worksheet counting Tabs from left from 1 To Total
    Rem 2) varables for some totals ;)
    Const TDays As Long = 30            'Total days just taken as 30            ' Long is very simple to handle, - final memory "size" type is known (123.456 and 000.001 have same "size" computer memory ) , and so a Address suggestion can be given for the next line when the variable is filled in.  '( Long is a Big whole Number limit (-2,147,483,648 to 2,147,483,647) If you need some sort of validation the value should only be within the range of a Byte/Integer otherwise there's no point using anything but Long.--upon/after 32-bit, Integers (Short) need converted internally anyways, so a Long is actually faster. )
    Dim NOHrsV2 As Double, HOHrsV2 As Double                                    ' I am proposing to use the underlying number an adjust as necerssary to get the reqired format
    Dim Dte As Date, DteNo As Long                                              ' I am hoping Dte will sort out getting a date in a format that I can use the Weekday function to see what week day it is and get that as a nuumber to check for..
    Rem 3) Loop through worksheets and give some Totals
    Dim Cnt As Long ' Loop Bound variable count for going through all worksheets
    '3a) main Loop start=====================================================
        For Cnt = 1 To Wb.Worksheets.Count                                      ' The Worksheets collection Object Property returns the number of worksheet items in the Workbook
         Let NOHrsV2 = 0: Let HOHrsV2 = 0                                       ' The varaibles are emtied before run for each worksheet
         Set wsStear = Wb.Worksheets.Item(Cnt)                                  ' At each loop the variable is set to the current Worksheet counting from the Cnt'ths tab from left
        Dim lr As Long                                                          ' Used for last row number in column E
         Let lr = wsStear.Range("E" & Rows.Count & "").End(xlUp).Row            ' The Range Object ( cell ) that is the last cell in the column of interest (CHOOSE a column typically that will always have a last Entry in any Data) ,( Row Number given by .Count Property applied to ( any Worksheet would do, so leaving unqualified is OK here, ) Spreadsheet Range Rows Property)    has the Property .End ( argument "Looking back up" ) appled to it. This Returns a new Range ( cell ) object which is that of the first Range ( cell ) with something in it "looking back up" in the XL spreadsheet from that last Cell. Then the .Row Property is applied to return a long number equal to the Row number of that cell:     Rows.Count is the very last row number in your Worksheet. It is different for earlier versions of Excel.  The End(xlUp) is the same as pressing a Ctrl+UpArrow key combination. The final ".Row" returns the row where the cursor stops after moving up.
        Dim FstDtaCel As Range: Set FstDtaCel = wsStear.Range("A1")             ' Worksheets Range(" ") Property used to return Range object of first cell in second row
    '3b) Data arrays from worksheet. We need columns E H I J      ....   Date ( Column E ) and Total hrs ( Column H ) are required to use in calculations
        Dim arrDte() As Variant, arrTotHrs() As Variant                         ' In the next lines the .Value2 or .value Property is applied a Range object which presents the Value or Value2 value or values in a single variable of appropriate type or a field of member Elements of varaint types.We are expecting the latter, so declare ( Dim ) a dynamic Array variable appropriately. It must be dynamic as its size will be defined at that assignment
         Let arrDte() = FstDtaCel.Offset(0, 4).Resize(lr, 1).Value    '  E      ' One thing you pick up when learning VBA programming is that referring to cells from one to another via an offset is both fundamental and efficient. That makes sense as Excel is all about using the offsets mentioned above. So like if you use them you can “cut out the middle man”. ( The middle man here might be considered as, for example, in VBA, using extra variables for different Range objects: A fundamental thing to do with any cell ( or strictly speaking the Range object associated to a cell ) is the Range Item Property of any range Object, through which you can “get at” any other Range object. http://www.excelforum.com/showthread...t=#post4563838 ( It is often quicker than using a separate variable for each Range object – probably as all the variable does is hold the offset , so you might as well use the offset in the first place.. )
         Let arrTotHrs() = FstDtaCel.Offset(0, 7).Resize(lr, 1).Value '  H      ' Similarly Another thing you pick up along the way is that the cells ( or strictly speaking the Range objects associated with it ) can be organised into groups of cells which then are also called Range objects and are organised in their constituent parts exactly the same as for the single cell Range object. Once again this is all an indication of organising so that we get at information by sliding along a specific amount ( offset value). The Offset and Resize properties therefore return a new range object. I use the .Value 2 here as i seemed to get it for .Value anyway, not sure why yet, - so i thought be on the safe side , get it always and work somehow with that for now and convert as necerssary.   Also 1 breadth Arrays due to Alan Intercept theory are held in such a ways as to be very effient in usage of values within:
        
        Dim arrInNorm() As Variant, arrInOver() As Variant
         Let arrInNorm() = FstDtaCel.Offset(0, 8).Resize(lr, 1).Value2 ' I      ' Normal Hrs ( Column I ) are needed as they must be set to zero for Holy ?? Holidays ?? Friday ??
         Let arrInOver() = FstDtaCel.Offset(0, 9).Resize(lr, 1).Value2 ' J      ' Overtime ( Column J ) is needed as it will be changed and then used in calculations
    '3c) Inner loop for rows
        Dim ShtCnt As Long ' Loop Bound Variable Count for hours columns looping
            For ShtCnt = 1 To UBound(arrDte(), 1) Step 1 '------------------- For "rows" in data arrays
    '3d) We need to check for a Holy?? Holiday?? Friday??    Adjust columns I and J so that column I has no hours for holiday day and total hours goes to over time hours with criteria 9 or less than 9 hrs all total hours added overtime, 10 or above 10 hrs one hour deducted from total hours and added to column J
             Let Dte = arrDte(ShtCnt, 1): Let DteNo = Weekday(Dte, [vbSunday])  ' I do not really nead this extra variable, but for dates I prefer always to do this to help in looking into the variable in Debugging
                If DteNo = 6 Then ' 6 I think is Friday, Nelson's Holy HoliDay ?
                    If (arrTotHrs(ShtCnt, 1) * 24) <= 9 Then                    '(i) If  Total Hrs are less than or equal to 9 ,Then all  Total Hrs are added to Overtime Hrs
                     Let arrInOver(ShtCnt, 1) = arrTotHrs(ShtCnt, 1)            ' Given To ' Added to arrInOver(ShtCnt, 1) + arrTotHrs(ShtCnt, 1)
                    ElseIf (arrTotHrs(ShtCnt, 1) * 24) > 9 Then                 ' (ii) If  Total Hrs are less greater than 9 , Then (  Total Hrs - 1 )  are added to Overtime Hrs
                     Let arrInOver(ShtCnt, 1) = arrTotHrs(ShtCnt, 1) - 1 / 24   ' Given To      ' arrInOver(ShtCnt, 1) + arrTotHrs(ShtCnt, 1) - 1 / 24 'Added to  1 hr less overtime for more than 9 hrs worked
                    End If
                 Let arrInNorm(ShtCnt, 1) = Empty                               ' (iii) As array is variant type can empty     Remove normal Hrs  Array for(Column I) is then set tom zerow for this "row"o
                Else ' No Holy Holiday
                End If
    '3e)
                If arrInNorm(ShtCnt, 1) <> 0 And arrInOver(ShtCnt, 1) <> 0 Then Let NOHrsV2 = NOHrsV2 + arrInOver(ShtCnt, 1) ' Normal Overtime is simply calculated from summing hours in column J  only If there are Overtime hours in column J And there are  Normal hours are in column I.
                If arrInNorm(ShtCnt, 1) = Empty And arrInOver(ShtCnt, 1) <> 0 Then Let HOHrsV2 = HOHrsV2 + arrInOver(ShtCnt, 1) ' Holiday  Overtime is simply calculated from summing hours in column J  only If there are Overtime hours in column J And there are  no Normal hours are in column I.
            Next ShtCnt '--------------------------End Inner loop for rows-----
    '3f) Paste out final Totals and days to current Worksheet
         Let wsStear.Range("G34").Value = NOHrsV2 * 24 'Normal Overtime is held in Array as fraction of a day
         Let wsStear.Range("J34").Value = HOHrsV2 * 24 'Holiday Overtime is held in Array as fraction of a day
         Let wsStear.Range("C34").Value = TDays ' The constant value of Total days is simply added to cell C34
    '3g) Normal   Hrs  ( Column I ) and Overtime Hrs ( Column J ) are  changed
         Let FstDtaCel.Offset(0, 9).Resize(lr, 1).Value2 = arrInOver() ' J       ' The required spreadsheet cells range has its Range Object .Value2 values filled an allowed direct assignment to an array of values
         Let FstDtaCel.Offset(0, 8).Resize(lr, 1).Value2 = arrInNorm() ' I
        Next Cnt '==End main Loop==============================================
    End Sub
    
    
    ' Rem Ref '_-   http://www.excelfox.com/forum/showth...0062#post10062
    '_-             http://www.excelfox.com/forum/showth...0012#post10012
    A Folk, A Forum, A Fuhrer ….

  10. #20
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,458
    Rep Power
    10

    Second Code for Nelson using Admin Formula Idea

    Second Code for nelson
    Post 9
    http://www.excelfox.com/forum/showth...0070#post10070





    Code:
    Sub IJAdjustKAddTotalAllWorksheet()     '  http://www.excelfox.com/forum/showthread.php/2144-Code-Required-to-calculate-number-of-days-worked-normal-overtime-and-holiday-overtime?p=10060#post10060
    Rem 1) Workbooks Info.
    Dim Wb As Workbook                  ' Dim: For Object variabls: Address location to a "pointer". That has all the actual memory locations (addresses) of the various property values , and it holds all the instructions what / how to change them , should that be wanted later. That helped explain what occurs when passing an Object to a Call ed Fucntion or Sub Routine By Val ue. In such an occurance, VBA actually  passes a copy of the pointer.  So that has the effect of when you change things like properties on the local variable , then the changes are reflected in changes in the original object. (The copy pointer instructs how to change those values, at the actual address held in that pointer). That would normally be the sort of thing you would expect from passing by Ref erence.  But as that copy pointer "dies" after the called routine ends, then any changes to the Addresses of the Object Properties in the local variable will not be reflected in the original pointer. So you cannot actually change the pointer.)
     Set Wb = ActiveWorkbook            ' Set: Fill or partially Fill: Setting to a Class will involve the use of an extra New at this code line. I will then have an Object referred to as an instance of a Class. At this point I include information on my Pointer Pigeon hole for a distinct distinguishable usage of an Object of the Class. For the case of something such as a Workbook this instancing has already been done, and in addition some values are filled in specific memory locations which are also held as part of the information in the Pigeon Hole Pointer. We will have a different Pointer for each instance. In most excel versions we already have a few instances of Worksheets. Such instances Objects can be further used., - For this a Dim to the class will be necessary, but the New must be omitted at Set. I can assign as many variables that I wish to the same existing instance
    Dim wsStear As Worksheet            ' Used for each Worksheet counting Tabs from left from 1 To Total
    Rem 2) varables for some totals ;)
    Const TDays As Long = 30            'Total days just taken as 30            ' Long is very simple to handle, - final memory "size" type is known (123.456 and 000.001 have same "size" computer memory ) , and so a Address suggestion can be given for the next line when the variable is filled in.  '( Long is a Big whole Number limit (-2,147,483,648 to 2,147,483,647) If you need some sort of validation the value should only be within the range of a Byte/Integer otherwise there's no point using anything but Long.--upon/after 32-bit, Integers (Short) need converted internally anyways, so a Long is actually faster. )
    Dim Dte As Date, DteNo As Long                                              ' I am hoping Dte will sort out getting a date in a format that I can use the Weekday function to see what week day it is and get that as a nuumber to check for..
    Rem 3) Loop through worksheets and give some Totals
    Dim Cnt As Long ' Loop Bound variable count for going through all worksheets
    '3a) main Loop start=====================================================
        For Cnt = 1 To Wb.Worksheets.Count                                      ' The Worksheets collection Object Property returns the number of worksheet items in the Workbook
         Set wsStear = Wb.Worksheets.Item(Cnt)                                  ' At each loop the variable is set to the current Worksheet counting from the Cnt'ths tab from left
        Dim lr As Long                                                          ' Used for last row number in column E
         Let lr = wsStear.Range("E" & Rows.Count & "").End(xlUp).Row            ' The Range Object ( cell ) that is the last cell in the column of interest (CHOOSE a column typically that will always have a last Entry in any Data) ,( Row Number given by .Count Property applied to ( any Worksheet would do, so leaving unqualified is OK here, ) Spreadsheet Range Rows Property)    has the Property .End ( argument "Looking back up" ) appled to it. This Returns a new Range ( cell ) object which is that of the first Range ( cell ) with something in it "looking back up" in the XL spreadsheet from that last Cell. Then the .Row Property is applied to return a long number equal to the Row number of that cell:     Rows.Count is the very last row number in your Worksheet. It is different for earlier versions of Excel.  The End(xlUp) is the same as pressing a Ctrl+UpArrow key combination. The final ".Row" returns the row where the cursor stops after moving up.
        Dim FstDtaCel As Range: Set FstDtaCel = wsStear.Range("A1")             ' Worksheets Range(" ") Property used to return Range object of first cell in second row
    '3b) Data arrays from worksheet. We need columns E H I J      ....   Date ( Column E ) and Total hrs ( Column H ) are required to use in calculations
        Dim arrInNorm() As Variant, arrInOver() As Variant                      ' In the next lines the .Value2 or .value Property is applied a Range object which presents the Value or Value2 value or values in a single variable of appropriate type or a field of member Elements of varaint types.We are expecting the latter, so declare ( Dim ) a dynamic Array variable appropriately. It must be dynamic as its size will be defined at that assignment
         Let arrInNorm() = FstDtaCel.Offset(0, 8).Resize(lr, 1).Value2 ' I      ' Normal Hrs ( Column I ) are needed as they must be set to zero for Holy ?? Holidays ?? Friday ??
         Let arrInOver() = FstDtaCel.Offset(0, 9).Resize(lr, 1).Value2 ' J      ' Overtime ( Column J ) is needed as it will be changed and then used in calculations
            Dim arrTotHrs() As Variant ' ,' ## ' arrDteClr() As Variant
         Let arrTotHrs() = FstDtaCel.Offset(0, 7).Resize(lr, 1).Value '  H      ' ' One thing you pick up when learning VBA programming is that referring to cells from one to another via an offset is both fundamental and efficient. That makes sense as Excel is all about using the offsets mentioned above. So like if you use them you can “cut out the middle man”. ( The middle man here might be considered as, for example, in VBA, using extra variables for different Range objects: A fundamental thing to do with any cell ( or strictly speaking the Range object associated to a cell ) is the Range Item Property of any range Object, through which you can “get at” any other Range object. http://www.excelforum.com/showthread.php?t=1154829&page=13&p=4563838&highlight=#post4563838 ( It is often quicker than using a separate variable for each Range object – probably as all the variable does is hold the offset , so you might as well use the offset in the first place.. )
                                                                                ' Similarly Another thing you pick up along the way is that the cells ( or strictly speaking the Range objects associated with it ) can be organised into groups of cells which then are also called Range objects and are organised in their constituent parts exactly the same as for the single cell Range object. Once again this is all an indication of organising so that we get at information by sliding along a specific amount ( offset value). The Offset and Resize properties therefore return a new range object. I use the .Value 2 here as i seemed to get it for .Value anyway, not sure why yet, - so i thought be on the safe side , get it always and work somehow with that for now and convert as necerssary.   Also 1 breadth Arrays due to Alan Intercept theory are held in such a ways as to be very effient in usage of values within
        Dim arrK() As String 'I know the size, but must make it dynamic as Dim declaration only takes numbers, and so I use ReDim method below wehich can also take variables or formulas
         ReDim arrK(1 To UBound(arrInNorm(), 1), 1 To 1) ' Any array first dimension ("row") will do
         
         'This will not work.             ' ## ' Let arrDteClr() = FstDtaCel.Offset(0, 4).Resize(lr, 1).Interior.Color  '  because .Interior property for a Range object shows only one value for the entire range which seems to be zero unless all the cells have a colour
        Dim arrDteClr() As Double, rngDts As Range
         Set rngDts = FstDtaCel.Offset(0, 4).Resize(lr, 1)
        Dim Rws As Long: ReDim arrDteClr(1 To lr, 1 To 1) ' so must loop in each Interior color value
            For Rws = 1 To UBound(arrDteClr(), 1) Step 1 'InnerLoop for dates background colors
             Let arrDteClr(Rws, 1) = rngDts.Item(Rws, "A").Interior.Color
            Next Rws
    '3c) Inner loop for rows
        Dim ShtCnt As Long ' Loop Bound Variable Count for hours columns looping
            For ShtCnt = 1 To UBound(arrDteClr(), 1) Step 1 '------------------- For "rows" in data arrays
    '3d) We need to check Interior color   Adjust columns I and J so that column I has no hours for holiday day and total hours goes to over time hours with criteria 9 or less than 9 hrs all total hours added overtime, 10 or above 10 hrs one hour deducted from total hours and added to column J   ..... and add a H or N in helper column K
                If arrDteClr(ShtCnt, 1) = 65535 Then
                    If (arrTotHrs(ShtCnt, 1) * 24) <= 9 Then                    '(i) If  Total Hrs are less than or equal to 9 ,Then all  Total Hrs are added to Overtime Hrs
                     Let arrInOver(ShtCnt, 1) = arrTotHrs(ShtCnt, 1)            ' Given To ' Added to arrInOver(ShtCnt, 1) + arrTotHrs(ShtCnt, 1)
                    ElseIf (arrTotHrs(ShtCnt, 1) * 24) > 9 Then                 ' (ii) If  Total Hrs are less greater than 9 , Then (  Total Hrs - 1 )  are added to Overtime Hrs
                     Let arrInOver(ShtCnt, 1) = arrTotHrs(ShtCnt, 1) - 1 / 24   ' Given To      ' arrInOver(ShtCnt, 1) + arrTotHrs(ShtCnt, 1) - 1 / 24 'Added to  1 hr less overtime for more than 9 hrs worked
                    End If
                 Let arrInNorm(ShtCnt, 1) = Empty                               ' (iii) As array is variant type can empty     Remove normal Hrs  Array for(Column I) is then set tom zerow for this "row"o
                 Let arrK(ShtCnt, 1) = "H" ' Give string, "" value of H for Holiday in Admin's help column K
                Else ' No Holy Holiday
                 Let arrK(ShtCnt, 1) = "N" ' give string N for normal
                End If
    '3e) ' from last code,  is not now used to calculate totals
            Next ShtCnt '--------------------------End Inner loop for rows-----
    '3f) Paste out final Totals and days to current Worksheet
         Let wsStear.Range("G35").Value = "=SUMIF(K1:K" & lr & ",""N"",J1:J" & lr & ")*24"
         Let wsStear.Range("J35").Value = "=SUMIF(K1:K" & lr & ",""H"",J1:J" & lr & ")*24"
         Let wsStear.Range("C34").Value = TDays ' The constant value of Total days is simply added to cell C34
    '3g) Normal   Hrs  ( Column I ) and Overtime Hrs ( Column J ) are  changed ' And can paste out help column if you like
         Let FstDtaCel.Offset(0, 9).Resize(lr, 1).Value2 = arrInOver() ' J       ' The required spreadsheet cells range has its Range Object .Value2 values filled an allowed direct assignment to an array of values
         Let FstDtaCel.Offset(0, 8).Resize(lr, 1).Value2 = arrInNorm() ' I
         Let FstDtaCel.Offset(0, 10).Resize(lr, 1).Value2 = arrK()     ' K
        Next Cnt '==End main Loop==============================================
    End Sub
    A Folk, A Forum, A Fuhrer ….

Similar Threads

  1. Tests and Notes on Range Referrencing
    By DocAElstein in forum Test Area
    Replies: 70
    Last Post: 02-20-2024, 01:54 AM
  2. Tests and Notes for EMail Threads
    By DocAElstein in forum Test Area
    Replies: 29
    Last Post: 11-15-2022, 04:39 PM
  3. Replies: 2
    Last Post: 07-23-2014, 12:12 PM
  4. Replies: 9
    Last Post: 07-02-2013, 06:59 PM
  5. Replies: 2
    Last Post: 12-04-2012, 02:05 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •