# VBForums CodeBank > CodeBank - Visual Basic 6 and earlier >  VB6 Built-in types extension library (FTypes)

## hwoarang

*Project sources are now located at BitBucket (https://bitbucket.org/hwoarang84/vbtypes/src/main/). See all related links at the bottom of the thread.*

This project extends Visual Basic 6.0 built-in data types by wrapping basic types into appropriate classes with lots of powerful functionality. You can work with types in much more convinient way (inline if needed), perform effective conversions, checks, transformations and take advantage from using other built-in features.

*CLASSES:*

- ArrayEx
- BooleanEx
- ByteEx
- CurrencyEx
- DateTimeEx
- DecimalEx
- IntegerEx
- ListEx
- LongEx
- DoubleEx
- SingleEx
- StringEx

*DOCUMENTATION*:

VBTypes Manual (PDF format)

*WIKI* *|* *HISTORY*

*SUBMODULES:*

- git submodule update --progress --init --force --remote -- "Ext/vbCore"

*TESTING*:

https://bitbucket.org/hwoarang84/vbt...i/Installation

*LATEST VERSION*:

https://bitbucket.org/hwoarang84/vbtypes/get/main.zip

*LICENSE AGREEMENTS:*

This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

----------


## VBClassic04

Nothing in the zip except the Dll.

----------


## hwoarang

> Nothing in the zip except the Dll.


My apologies. Corrected now.

----------


## hwoarang

*Attachtment updated:*

- New ByteEx class added;
- StringEx: new functions added
- Minor fixes and improvements

----------


## xxdoc123

good ider ...

----------


## hwoarang

> good ider ...


Hopefully it will help people to write dayly routines concerning types "vice-versa" faster and increase code readability. I started to use it within my current project also. At least at start I eliminated lots of code lines and optimized some loops for strings.

After some days a new version of FTypes will be available - with powerfull ArrayEx class  :Smilie:

----------


## MikiSoft

Great, keep it up!  :Smilie: 
I have some suggestions, though. Can you make a support for Currency type of the variable, later extending that on its Decimal subtype (which is poorly supported by native numeric functions in VBA/6)? Also, it would be great if StringEx can be used for numerical operations too, i.e. for storing very big numbers (for which there's no possibility to fit them even into Currency) and doing calculations with them (addition, subtraction, division, multiplication).

P.S. A word in the title is a bit wrong spelled - it should write "buil*t*-in".

----------


## hwoarang

> Great, keep it up! 
> I have some suggestions, though. Can you make a support for Currency type of the variable, later extending that on its Decimal subtype (which is poorly supported by native numeric functions in VBA/6)? Also, it would be great if StringEx can be used for numerical operations too, i.e. for storing very big numbers (for which there's no possibility to fit them even into Currency) and doing calculations with them (addition, subtraction, division, multiplication)?
> 
> P.S. A word in the title is a bit wrong spelled - it should write "buil*t*-in".


Hi ) Thank you for your ideas - i will try to include this features after I will handle ArrayEx functionality (now it is can only bring info about array - almost nothing more). Also I will include a base of Currency type in next version (+ Single type).

P.S. since i'm not a native english speaker - sorry for mistake in topic header  :Smilie:

----------


## MikiSoft

No problem, I'm also not native English speaker.  :Stick Out Tongue: 
I'm thinking of joining all familiar non-float variable types (Byte, Integer, Long...) into one - Number, and on the other side all float types into Float, or even both combined into only one - would be also an good idea. So, you would just have to pass a number (either in String or Variant form) to it/them and the parsing routine "automagically" will decide in which type of variable to store it.  :Smilie:

----------


## hwoarang

I would say that for some particular purpose that could be good idea, but not for FTypes. The reason is that a _GOD_ object is not good from architectual point of view and also from performance side. I can say 100% is that FType library will follow _strong type_ model as much as possible. At least for now numeric types have Parse & convert methods that can be used.

But as next steps I can think of common interface to be able to add some kind of additional Numeric class that can parse a value and return needed type.

----------


## hwoarang

*Attachment updated:*

Ftype 1.1.0 (see topic header for details)

----------


## hwoarang

Attachment updated:

Ftype 1.3.0 (see topic header for details). Lots of work was done with ArrayEx ... and new methods are to be added soon too.

----------


## hwoarang

Attachment updated:

*FTypes 1.4.0* (see topic header for details). There is now a possibility to work with decimal numbers and achieve high precision.

----------


## hwoarang

Attachment updated:

*FTypes 1.4.1* (see topic header for details). Documentation included.

----------


## hwoarang

Attachment updated:

*FTypes 1.4.2* (see topic header for details).

----------


## hwoarang

Attachment updated:

*FTypes 1.4.3* (see topic header for details). Lots of fixes for ArrayEx class - now it is stable and usable !  :Smilie:

----------


## Resurrected

Lovely. I will try this out.

----------


## hwoarang

Attachment updated:

*FTypes 1.5.4* (see topic header for details).

----------


## Elroy

hwoarang,

This is all an interesting idea, but here's a problem I just don't think you're going to overcome.

Example #1:



```

Option Explicit

Private Sub Form_Load()
    Dim lIndex As Long
    Dim nStart As Single
    Dim nEnd As Single


    Dim lToIncrement As Long



    nStart = Timer
    For lIndex = 1 To 10000000
        lToIncrement = lToIncrement + 1
    Next lIndex
    nEnd = Timer


    MsgBox nEnd - nStart
    Debug.Print nEnd - nStart

    Unload Me
End Sub


```

And the output (seconds to execute):



```
 0.3242188
```

And then, we use your stuff, as shown in how lToIncrement is declared.  I even initialized it to remove the overhead of initially instantiating the COM object from the timing.



```

Option Explicit

Private Sub Form_Load()
    Dim lIndex As Long
    Dim nStart As Single
    Dim nEnd As Single


    Dim lToIncrement As LongEx
    Set lToIncrement = New LongEx
    lToIncrement = -1
    lToIncrement = 0



    nStart = Timer
    For lIndex = 1 To 10000000
        lToIncrement = lToIncrement + 1
    Next lIndex
    nEnd = Timer


    MsgBox nEnd - nStart
    Debug.Print nEnd - nStart

    Unload Me
End Sub

```

This time, our output is (seconds):



```
 5.480469
```

This is over a *16 times* reduction in performance.  In most situations, this type of performance hit just isn't going to be acceptable.

I suppose there are specific situations where "enhanced" types may be useful, but one should be aware of this rather dramatic performance hit when using these.

Just as an FYI, when using the native types, they operate rather directly with memory and the CPU.  However, when using a class, you must navigate through the class addressing everytime you use one of its properties (even if it's the default property).  There's just no way around this.  And the above is even using early-binding.

If we were to use late-binding (such as using 'As Variant' or 'As Object' in our declaration), things would even get another order of magnitude worse, as follows:



```

Option Explicit

Private Sub Form_Load()
    Dim lIndex As Long
    Dim nStart As Single
    Dim nEnd As Single


    Dim lToIncrement As Object
    Set lToIncrement = New LongEx
    lToIncrement = -1
    lToIncrement = 0



    nStart = Timer
    For lIndex = 1 To 10000000
        lToIncrement = lToIncrement + 1
    Next lIndex
    nEnd = Timer


    MsgBox nEnd - nStart
    Debug.Print nEnd - nStart

    Unload Me
End Sub


```

This time, the output is (seconds):



```
 57.06641
```

... *over a 175 times decrease* in performance, entirely unacceptable.

Again, a nice idea, but certainly not viable for a complete replacement for the built-in types.

Best Regards,
Elroy

----------


## hwoarang

Hi Elroy.

The code you've posted has nothing common with the idea of FTypes - I'm sorry. Moreover, your sample is sensless there. Because for anyone who is about to use Ftypes like this - the will always be a performance leaks (i'm also will not speak about late binding ...). The idea is to make less code lines when for example .. you need to convert Long to Integer and then get high word ... anything that Ftypes support - doesn't matter. The performance is not about to be discussed for people like me and you - guess who knows what are things about in VB6.

But .. for your particular case I just did a Sub for incrementing that acts less than 0.5 of a second.

If you want a performance increase - there is a StringEx Concat and rest methods that are much faster than pure VB string opertions. Guess you looked at code already and there is no need to comment.

Anyway, thatnk you for your post. At least I will add special math methods for maximum time safe in cases like self + and -.

----------


## winkey88@163.com

I try the Samples, and find #3 is not working well. 
I modify it, and this time,it produces 355

    MsgBox a.Create(vbLong, 2&, Array(0&, 4&), Array(0&, 8&)).Add(b).Item(4, 9)

----------


## hwoarang

> I try the Samples, and find #3 is not working well. 
> I modify it, and this time,it produces 355
> 
>     MsgBox a.Create(vbLong, 2&, Array(0&, 4&), Array(0&, 8&)).Add(b).Item(4, 9)


Yes. Thank you. This was a mistake =)

----------


## hwoarang

Attachment updated:

*FTypes 1.5.5* (see topic header for details). _NOTE_: this version is not binary compatible with previous versions.

----------


## hwoarang

Attachment updated:

*FTypes 1.5.6* (see topic header for details).

----------


## hwoarang

Attachment updated:

*FTypes 1.5.7* (see topic header for details). *NOTE*: this version is not binary compatible with previous versions.

----------


## hwoarang

Full documentation available now (see link above FTypes.zip download). PDF format. With table of content (if supported by viewer) & working links. 3.47 Mb size.

----------


## hwoarang

Attachment updated:
*
FTypes 1.5.8* (see topic header for details). NOTE: this version is not binary compatible with previous versions, but starting from this point backward compatibility will remain.

----------


## hwoarang

Attachment updated:

*FTypes 1.5.9* (see topic header for details).

----------


## hwoarang

Attachment updated:

*FTypes 1.6.0* (see topic header for details).

----------


## hwoarang

Attachment updated:

*FTypes 1.6.1* (see topic header for details). Note: ArrayEx.Sort method is planned to be introduced in next version.

----------


## hwoarang

Attachment updated:

*FTypes 1.6.2* (see topic header (samples, rev. history and manual) for details).

----------


## hwoarang

Attachment updated:

*FTypes 1.6.3* (see topic header for details).

----------


## hwoarang

Attachment updated:

*FTypes 1.6.4* (see topic header for details + sample #6).

----------


## Simos

Good work. I'll keep testing and use it.

----------


## hwoarang

> Good work. I'll keep testing and use it.


Thanks a lot) Hope lib helps with daily code routines.

----------


## hwoarang

Attachment updated:

*FTypes 1.6.5* (see topic header for details).

----------


## Krool

What about a Change event? So when the extended variable is declared like "Private WithEvents" it raises an event "Change", but only when the value gets effectively changed.

Example:


```
Private WithEvents bTest As BooleanEx
Private bAnother As Boolean

Sub DoTest()
bTest = Not bTest ' Will raise event
bTest = bTest ' No change, do not raise
End Sub

Private Sub bTest_Change()
bAnother = bTest
End Sub
```

----------


## hwoarang

Surprise =) Currently working on it (exactly same mechanism in another private project). Hope to release new version of FLib soon (one-two weeks maybe) with events, interfaces and ArrayEx extensions.

----------


## hwoarang

Hi guys. Any notes, bugs or else maybe ?

----------


## dreammanor

Thanks for sharing. I haven't used it yet, but it looks pretty good, especially ArrayEx and StringEx. When I have time, I'll test it.

I have seen a MinFrameWork(Vibian) on PsCode. It is a simple but powerful COM library for VB6 which emulates/bring some VB.NET functions.  Here is its link, may be helpful to you and others:
http://www.planet-source-code.com/vb...01715423264095

I guess maybe someone will use VB6 to simulate all .NET class libraries. That would be a very interesting thing.

----------


## hwoarang

Thanks for a link, dreammanor. That can be very usefull for vb6 developers. As for me - for my projects I have my own private framework lib called FLib, just did not share it yet because guess it will not be something new.

For FTypes I really can note that core idea was to bring some kind of VB.NET style. Of course only for base data types - no filesystem, registry or other routines that are not part of project mainstream.

P.S. Will be glad to have a feedback or maybe get reports of some issues in FTypes. Project is and will be supported and extended  :Smilie:  Thinking about ArrayEx subtype called ListEx for single-dimensioned arrays only ...

----------


## hwoarang

Attachment updated:

*FTypes 1.6.7* (see topic header for details).

----------


## Jonney

1. Please add hash related functions for StringEx.
2. How to use ArrayEx? Please make one demo.

----------


## hwoarang

> 1. Please add hash related functions for StringEx.
> 2. How to use ArrayEx? Please make one demo.


For ArrayEx samples look in topic header example #3 and/or FTypes manual ArrayEx section (see link in topic header).

----------


## hwoarang

> 1. Please add hash related functions for StringEx.
> 2. How to use ArrayEx? Please make one demo.


Attachment updated:

*FTypes 1.6.8* (Encrypt/Decrypt methods added for StringEx).

----------


## AAraya

Thanks for your extensive work on this and for making it freely available.  I've downloaded it and will begin evaluating it.

----------


## AAraya

Here's a thought for the StringEx class: Expand the Case options to include more than just Upper and Lower.   Other common case types I regularly use are: Sentence Case, Title Case and less frequently CamelCase, snake_case, kebab-case.  See this Wikipedia entry on the various options: https://en.wikipedia.org/wiki/Letter_case#Sentence_case

So here's a proposed list of case related methods:
touppercase
tolowercase
tosentencecase
totitlecase
tocamelcase
tosnakecase
tokebabcase

I know that the last three are a bit less common but i include them primarily for completeness.

----------


## DEXWERX

> Thanks for sharing. I haven't used it yet, but it looks pretty good, especially ArrayEx and StringEx. When I have time, I'll test it.
> 
> I have seen a MinFrameWork(Vibian) on PsCode. It is a simple but powerful COM library for VB6 which emulates/bring some VB.NET functions.  Here is its link, may be helpful to you and others:
> http://www.planet-source-code.com/vb...01715423264095
> 
> I guess maybe someone will use VB6 to simulate all .NET class libraries. That would be a very interesting thing.


i guess you haven't heard of vbcorlib ?

http://vbcorlib.blogspot.com/

it doesn't have GDI+ but it's most of the cor system classes.

----------


## hwoarang

> i guess you haven't heard of vbcorlib ?
> 
> http://vbcorlib.blogspot.com/
> 
> it doesn't have GDI+ but it's most of the cor system classes.


That is the case when I say - I haven't =) Thanks for info. Quite interesting to know - really

----------


## hwoarang

> Here's a thought for the StringEx class: Expand the Case options to include more than just Upper and Lower.   Other common case types I regularly use are: Sentence Case, Title Case and less frequently CamelCase, snake_case, kebab-case.  See this Wikipedia entry on the various options: https://en.wikipedia.org/wiki/Letter_case#Sentence_case
> 
> So here's a proposed list of case related methods:
> touppercase
> tolowercase
> tosentencecase
> totitlecase
> tocamelcase
> tosnakecase
> ...


Hey. Thank for extension ideas. That is not going to overload a project, opposite - direct enhancment.

----------


## hwoarang

Attachment updated:

*FTypes 1.6.9* (see topic header for details).

----------


## fabel358

Sorry for my question: where is the "Ftypes.dll" in the zip folder?

----------


## hwoarang

> Sorry for my question: where is the "Ftypes.dll" in the zip folder?


Hi. This is open source project. You have to open this in VS 6 (with sp6) and build it yourself.

----------


## fabel358

VS6 with SP& return: "_Unable to set component compatible with version: ...\bin\dll\FTypes.dll_". It's right? What's wrong?

----------


## hwoarang

> VS6 with SP& return: "_Unable to set component compatible with version: ...\bin\dll\FTypes.dll_". It's right? What's wrong?


You need to open FTypes project properties and go to "Component" tab. Within "Version Compatibility" settings enable "No compatibility" option. Do save. Compile project. Go back to settings and now choose "Binary Compatibility" and set appropriate path to just compiled DLL.

----------


## hwoarang

Attachment updated:

*FTypes 1.8.0* (see topic header for details). *NOTE*: this version is not binary compatible with previous versions.

----------


## hwoarang

Attachment updated:

*FTypes 1.8.1* (see topic header for details). *NOTE*: this version is not binary compatible with previous versions.

----------


## hwoarang

Attachment updated:

*FTypes 1.9.0* (see topic header for details). *NOTE*: this version is not binary compatible with previous versions.

----------


## DEXWERX

You might want to add support for Enumeration (IEnumVARIANT) to your ArrayEx class.
I believe Olaf posted an example using a lightweight COM Objects. I also can post an example, but it requires a typelib for IEnumVARIANT, and patching an interface pointer.

----------


## hwoarang

> You might want to add support for Enumeration (IEnumVARIANT) to your ArrayEx class.
> I believe Olaf posted an example using a lightweight COM Objects. I also can post an example, but it requires a typelib for IEnumVARIANT, and patching an interface pointer.


Thank you. You are welcom to post it ) I thought about enum. Yet I have a solution of .ForEach (not included into project) that requires a pointer to a custom function (callback) in a module. But I do not like this actually.

----------


## DEXWERX

You're going to need some sort of callback to implement an Enumerator Class. That's kind of what the IEnumVARIANT interface is. I've attached my implementation, which is adapted from .NET.
It uses my typelib, to provide the interface definitions, and pointer functions.

In the example project, the enumerator class must implement IEnumerator. I use an Enumerator class that wraps IEnumerator, and implements IEnumVARIANT. That class that also patches IEnumVARIANT::Next with a static function so that it can return S_FALSE to end the enumeration. 

If you were going to add this to your lib, you would have to expose an IEnumerator type of interface/callback as well. The actual implementation of IEnumVARIANT however would need to be done by a lightweight com object, or using a typelib assisted approach. 

*edit:* actually you wouldn't need to expose the IEnumerator interface unless you wanted to allow users to also piggyback on your implementation, with their custom enumerators. You wouldn't even need an IEnumerator interface, you could implement IEnumVARIANT directly on ArrayEX allowing you For Each on your array class, without cluttering up your object model. You don't even need a seperate class to do the enumeration, just put it all in ArrayEx.

(feel free to decompile the typelib using OLE Viewer. I haven't released the source due to the fact that some of the assisting files are copyright MS)


*edit2:* I believe this can be done without any typelib, so I'll post an example you can adapt when I get a chance.

----------


## DEXWERX

Here's a minimal implementation of a custom Enumerator that enables the use of For Each in VB6 without a typelib. I created a Light Weight COM Object. I'll post a full implementation to the code bank at some point, but this should be enough to get you started.

You're Enumerable object (ArrayEx for example) must have a NewEnum function with the Dispatch ID set to -4 (DISPID_NEWENUM)
1) Paste this function into ArrayEx:



```
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' IEnumerable
Public Function GetEnumerator() As IEnumVARIANT
' The ProcedureID must be set to -4 (DISPID_NEWENUM)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Set GetEnumerator = NewEnumerator(Me, Length - 1, 0)
End Function
```

2) Put your edit cursor in the function
3) Click the menu "*Tools-->Procedure Attributes...*"
4) Make sure it says "*Name: GetEnumerator*"
5) Click *Advanced>>*
6) Put -4 for the Procedure ID.
7) Click *OK*
8) Add the following Module.




```
' Copyright © 2017 Dexter Freivald. All Rights Reserved. DEXWERX.COM
'
' MEnum.bas
'
' Minimal implementation of IEnumVARIANT to support For Each in VB6
'   - TODO: full implementation for use outside of VB6 runtime
'
Option Explicit

Private Type TENUMERATOR
    VTablePtr   As Long
    References  As Long
    Enumerable  As Object
    Index       As Long
    Upper       As Long
End Type

Private Declare Function FncPtr Lib "msvbvm60" Alias "VarPtr" (ByVal FunctionAddress As Long) As Long
Private Declare Function GetMem4 Lib "msvbvm60" (Src As Any, Dst As Any) As Long
Private Declare Function CopyBytesZero Lib "msvbvm60" Alias "__vbaCopyBytesZero" (ByVal Length As Long, Dst As Any, Src As Any) As Long
Private Declare Function CoTaskMemAlloc Lib "ole32" (ByVal cb As Long) As Long
Private Declare Sub CoTaskMemFree Lib "ole32" (ByVal pv As Long)
Private Declare Function VariantCopyToPtr Lib "oleaut32" Alias "VariantCopy" (ByVal pvargDest As Long, ByRef pvargSrc As Variant) As Long

Private Property Let DeRef(ByVal Address As Long, ByVal Value As Long)
    GetMem4 Value, ByVal Address
End Property

Private Property Get ObjRef(ByRef Obj As IUnknown) As Long
    GetMem4 Obj, ObjRef
End Property

Private Property Let ObjRef(ByRef Obj As IUnknown, ByVal Value As Long)
    GetMem4 Value, Obj
End Property

Public Function NewEnumerator(ByRef Enumerable As Object, _
                              ByVal Upper As Long, _
                              Optional ByVal Lower As Long _
                              ) As IUnknown
    Static VTable(3) As Long
    If VTable(0) = 0 Then
        VTable(0) = FncPtr(AddressOf IUnknown_QueryInterface)
        VTable(1) = FncPtr(AddressOf IUnknown_AddRef)
        VTable(2) = FncPtr(AddressOf IUnknown_Release)
        VTable(3) = FncPtr(AddressOf IEnumVARIANT_Next)
    End If
    
    Dim This As TENUMERATOR
    With This
        .VTablePtr = VarPtr(VTable(0))
        .Index = Lower
        .Upper = Upper
        .References = 1
        Set .Enumerable = Enumerable
    End With
    
    Dim pThis As Long
    pThis = CoTaskMemAlloc(LenB(This))
    CopyBytesZero LenB(This), ByVal pThis, This
    GetMem4 pThis, NewEnumerator
End Function

Private Function IUnknown_QueryInterface(ByRef This As TENUMERATOR, _
                                         ByVal riid As Long, _
                                         ByVal ppvObject As Long _
                                         ) As Long
    DeRef(ppvObject) = VarPtr(This)
    This.References = This.References + 1
End Function

Private Function IUnknown_AddRef(ByRef This As TENUMERATOR) As Long
    This.References = This.References + 1
    IUnknown_AddRef = This.References
End Function

Private Function IUnknown_Release(ByRef This As TENUMERATOR) As Long
    This.References = This.References - 1
    IUnknown_Release = This.References
    If This.References = 0 Then
        Set This.Enumerable = Nothing
        CoTaskMemFree VarPtr(This)
    End If
End Function

Private Function IEnumVARIANT_Next(ByRef This As TENUMERATOR, _
                                   ByVal celt As Long, _
                                   ByVal rgVar As Long, _
                                   ByVal pceltFetched As Long _
                                   ) As Long
    If This.Index > This.Upper Then
        IEnumVARIANT_Next = 1
    Else
        VariantCopyToPtr rgVar, This.Enumerable(This.Index) ' Calls default Property!
        This.Index = This.Index + 1
    End If
End Function
```


NOTE: the IEnumVARIANT_Next() calls your enumerable collection's default property with an Index value, so make sure the default property is set, or adapt the method to properly grab your object's value by Index.

Good luck!


*edit:* posted more filled out version to the CodeBank. --> http://www.vbforums.com/showthread.p...hout-a-typelib

----------


## hwoarang

> Here's a minimal implementation of a custom Enumerator that enables the use of For Each in VB6 without a typelib. I created a Light Weight COM Object. I'll post a full implementation to the code bank at some point, but this should be enough to get you started.


Thank you DEXWERX. That is exactly what I need) Sorry - I mentioned your post here only yesterday - somehow did not get email notification =(.

1.9.2 versioon of FTypes will include your implementation.

----------


## hwoarang

Attachment updated:

*FTypes 1.9.1* (see topic header for details). *NOTE*: this version is not binary compatible with previous versions.

----------


## hwoarang

Attachment updated:

*FTypes 1.9.2* (see topic header for details).

Thanks to *DEXWERX* for IEnumVARIANT implementation  :wave:  You can look how your source code was adjusted and optimized for usage within ListEx.

----------


## hwoarang

Attachment updated:

*FTypes 1.9.21* (see topic header for details).

----------


## hwoarang

*Project sources are now located at GitHub (https://github.com/hwoarang84/FTypes). Source code here won't be updated any more. See all related links at the begining of the thread.*

----------


## hwoarang

*FTypes 1.9.3*

- StringEx: add HashCode property;
- Documentation updated.

----------


## hwoarang

*FTypes 1.9.4*

- StringEx: increase performance of Asc, Compare and Find;
- Documentation updated.

----------


## hwoarang

*FTypes 1.9.5*. NOTE: this version is not binary compatible with previous versions.

- ListEx: Add FilterAt and RemoveAt methods, rework Filter and Remove methods (change parameters and possibilities);
- Documentation updated.

----------


## hwoarang

*FTypes 1.9.51*

- Optimize ArrayElementGet and ArrayElementSet methods.

----------


## hwoarang

*FTypes 1.9.52*

- Increase ArrayEx & ListEx performance by removing of VarPrt usage.

----------


## hwoarang

*FTypes 1.9.6* (10-Jan-2018)

- ListEx: add IndexOf property, optimize internal usage of Count property.

----------


## hwoarang

*FTypes 1.9.7* (13-Jan-2018)

- IntegerEx: add ShiftL and ShiftR methods;
- LongEx: add ShiftL and ShiftR methods.

----------


## Elroy

Hi hwoarang,

It looks like you're really trying to make some classes that'll be useful under certain circumstances.  I just took a look at your latest source code.  Didn't try to run it because of some DLL it needed, but I still perused it.

One thing I noticed was the occasional use of "On Error Resume Next".  I certainly use that occasionally, but I've learned to always terminate a block using it with "On Error Goto 0".  The reason for this is that the Err object is left "dirty" if you get an error.  Here's an example of what I mean:

*Just throw into Form1:*


```

Option Explicit

Private Sub Form_Load()

    test1
    MsgBox Err

End Sub

Sub test1()
    On Error Resume Next
    Dim a As Long
    a = 1 / 0
End Sub

```

If a procedure higher up the call chain is monitoring for possible errors (possibly also using On Error Resume Next), returning from one of your procedures with an error set can cause havoc.

For instance, here are a couple of procedure where I use it:



```

Public Function NaN() As Double
    ' Math can be done on these, but nothing changes.
    ' They can NOT be used in "if NaN = NaN Then", or an overflow will result.
    On Error Resume Next
        NaN = 0 / 0
    On Error GoTo 0
End Function

```



```

Public Function IsDimmedLng(TheArray() As Long, Optional FailOnZeroNegOne As Boolean = True) As Boolean
    On Error Resume Next
        If FailOnZeroNegOne Then ' Some arrays can be 0 to -1.
            IsDimmedLng = (LBound(TheArray) <= UBound(TheArray))    ' Will error (leaving IsDimmedLng = False) if not dimensioned.
        Else
            IsDimmedLng = (LBound(TheArray) = LBound(TheArray))     ' Will error (leaving IsDimmedLng = False) if not dimensioned.
        End If
    On Error GoTo 0
End Function

```

As you can see, I've actually gotten into the habit of indenting between an "On Error Resume Next" and "On Error Goto 0" block.  Also, I must mention that Bonnie West was who brought this to my attention a while back.


Also, if you're looking for more enhancements, how about adding the LongLong type, and also adding your bit-shifting to both the Decimal and LongLong type.  Also, bit-shifting in the Currency will be useful to some.

Swapping Endianness may also be useful to some people.  This could apply to any of the types (excluding Strings and Bytes, I suppose).

Best Regards,
Elroy

EDIT1:  Also, some other ideas would be a SafeMult and SafeDiv, possibly returning NaN if it fails.  Also, adding the NaN may be a good idea, but that'll only be available for Singles and Doubles.  I've also got an IsNaN function...



```

Public Function IsNan(v As Variant) As Boolean
    ' This is just for "Single" and "Double" IEEE floating point.
    Dim iType As Long
    Dim s As String
    iType = VarType(v)
    If iType <> vbSingle And iType <> vbDouble Then Exit Function
    s = CStr(v)
    If InStr(s, "#IND") Or InStr(s, "#QNAN") Or InStr(s, "#SNAN") Then IsNan = True
End Function

Public Function IsInfinity(v As Variant) As Boolean
    ' This is just for "Single" and "Double" IEEE floating point.
    Dim iType As Long
    Dim s As String
    iType = VarType(v)
    If iType <> vbSingle And iType <> vbDouble Then Exit Function
    s = CStr(v)
    If InStr(s, "#INF") Then IsInfinity = True
End Function

```

Also, another idea that comes to mind for Longs (and LongLongs if you implement them), is an UnsignedAdd.  Many might call this a PtrAdd.  It would effectively treat a Long (and LongLong) as unsigned.


EDIT2:  Also, if it were me, I'd tend to build Array options into each one of them.  Here's an example where I've recently done that with a UDT:



```

Option Explicit
'
Dim VecArray() As VecType
Dim TheLabel As String
'

Friend Function Count() As Long
    Count = UBound(VecArray) - LBound(VecArray) + 1
End Function

Friend Function LoBound() As Long
    LoBound = LBound(VecArray)
End Function

Friend Function HiBound() As Long
    HiBound = UBound(VecArray)
End Function

Friend Property Get Label() As String
    Label = TheLabel
End Property

Friend Property Let Label(sLabel As String)
    TheLabel = sLabel
End Property

Friend Function IsDimmed() As Boolean
    On Error Resume Next
        IsDimmed = (LBound(VecArray) <= UBound(VecArray))
    On Error GoTo 0
End Function

Friend Sub RedimData(lo As Long, hi As Long)
    ReDim VecArray(lo To hi)
End Sub

Friend Sub EraseData()
    Erase VecArray
End Sub

Friend Property Get Frame(i As Long) As VecType
    Frame = VecArray(i)
End Property

Friend Property Let Frame(i As Long, vec As VecType)
    VecArray(i) = vec
End Property

Friend Property Get X(i As Long) As Double
    X = VecArray(i).X
End Property

Friend Property Let X(i As Long, X As Double)
    VecArray(i).X = X
End Property

Friend Property Get Y(i As Long) As Double
    Y = VecArray(i).Y
End Property

Friend Property Let Y(i As Long, Y As Double)
    VecArray(i).Y = Y
End Property

Friend Property Get Z(i As Long) As Double
    Z = VecArray(i).Z
End Property

Friend Property Let Z(i As Long, Z As Double)
    VecArray(i).Z = Z
End Property


```

And here's the UDT declaration for that:



```

Public Type VecType
    ' This is used for both 3D spatial vectors, and Euler angles as well.
    X As Double
    Y As Double
    Z As Double
End Type


```

But I'm mainly just showing the RedimData, EraseData, Count, LoBound, HiBound, & IsDimmed functions.  When all done in this way, you have to put your array index in a slightly different place in the code, but it's certainly useful under certain circumstances.  Also, if each of your classes was *optionally* an array, you could have an IsArray function.


Also, something else I noticed is that you make absolutely no use of the *Friend* declaration, but I also see that you have this set to be compiled as an ActiveX.dll.  If I were actually considering using these, I'd certainly just compile them into my main project, and not mess with an ActiveX.dll.  And, in that case, I'd want all the exposed class methods declared as Friend.  Just a note about that might be warranted.

----------


## hwoarang

Hi, Elroy.

Thank you for you attension to the project. I will try to point basics concening why it was done that way but not another.

1) FTypes project seems to ask only for stdole2.tlb at buid time. No other referencies are needed. There can only be one confusion, because source code project settings have backward compatibility enabled. But when you just download sources you of course do not have any DLL builded before - so you have to temporary disable compatibility, build and then enable this back;

2) I do not agree about your statements of dirty Err object. First, I use On Error Resume Next by design - FTypes should not produce any errors in normal way. Second, FTypes is handled as DLL that of course have own treatment of Err object that do not intersect with Err object in client application. To pass any info about error to the client you need to add "static" classes and use its methods in client. 

3) I agree about bitwise shifting for rest classes - but I've just made it for Integer and Long - so next enhancement is planned  :Smilie: 

4) As you've noticed already - FTypes have ArrayEx and ListEx classes. Second one is a generic single dimensioned array that can hold any type. First one is multi. You can't predict what count of dims it will be - you can write any array that OLE safaarray supports there. Then you are free to select a range from one dim and convert it to List - for example.
I do not like to introduce any custom types without need and particulary types that assign any borders to planned or implemented project functonality. That is why i use ParamArray arguments in ArrayEx.Item property.

5) You can use spesial ToList method of each class to convert it to array. ArrayEx itself have BoundU/L, Destroy and Redim (as well as ListEx)...

6) No Friend declares is the answer why there in no Error Goto 0 actually. There should be no conserns to use Active DLLs in VB6 at all i think. And FTypes was designed to be this. There is no big sense to put all in you APP like built-in stuff

Hopefuly, I understood you correctly  :Smilie:  If you have other concerns - let me know. I'm glad to communicate with all users of the project and help them with any issues or plan future implementation with your help.

Unfortunatly, for now it is pretty rare case to see such informative replies as yours (( And I'm happy to read and answer this =)

----------


## hwoarang

*FTypes 1.9.71* (14-Jan-2018)

- ListEx: fix impossibility to enlarge array items count using Resize method due to wrong argument validation.

----------


## hwoarang

*FTypes 1.9.72* (14-Jan-2018)

- Fix memory corruption in internal ArrayDestroy method.

----------


## hwoarang

*FTypes 1.9.73* (14-Jan-2018)

- ListEx: add Sorted property (see updated documentation);
- Documentation updated.

----------


## hwoarang

*FTypes 1.9.74* (16-Jan-2018)

- ListEx: fix missing checks for array items count (f.e. caused Distinct to add new item by accident);
- ListEx: fix not inherited Sorted flag after Clone method using.

----------


## hwoarang

*FTypes 1.9.75* (22-Jan-2018)

- TypesFactory: use Parse method instead of Value property.

----------


## hwoarang

*FTypes 1.9.8 (17-Feb-2018)* NOTE: this version is not binary compatible with previous versions.

- ListEx: add Reverse method;
- StringEx: move Compare method to Equals property, Find method to IndexOf property.

----------


## hwoarang

FTypes project moved to BitBucket (https://bitbucket.org/hwoarang84/ftypes/src)

----------


## loquat

this link needs G:\Shared\Enumerator.bas
https://bitbucket.org/hwoarang84/ftypes/get/master.zip

OK, I found it here
http://www.vbforums.com/showthread.p...hout-a-typelib

----------


## hwoarang

> this link needs G:\Shared\Enumerator.bas
> https://bitbucket.org/hwoarang84/ftypes/get/master.zip
> 
> OK, I found it here
> http://www.vbforums.com/showthread.p...hout-a-typelib


G:\Shared is your local interpretation of reference. There are *notes in project WIKI* (https://bitbucket.org/hwoarang84/ftypes/wiki/Home) that there is a dependency from https://bitbucket.org/hwoarang84/shared/src. Enumerator.bas is located there and you need to use it from there - because code is adapted to FTypes.

----------


## loquat

StringEx.Compare is not now in dll
but the demo use it in Function TestEx

----------


## hwoarang

> StringEx.Compare is not now in dll
> but the demo use it in Function TestEx


Yes. You're right. Thanks. Demo is bit obsolete - i will try to adjust it soon. As for Compare method - it is now Equals property. Done so because of unified approach to methods that should return class self instance (except Clone). Only properties can return other data types.

In latest version you need to recompile dll without binary compatibility for first time.

----------


## hwoarang

*FTypes project needs to be recompiled* by developers who use it since changes in referenced Enumerator.bas module of Shared project (https://bitbucket.org/hwoarang84/sha...182ab345a57e0d).

----------


## ChenLin

Test code error ViewString written frmString, Compare does not exist.

----------


## hwoarang

*FTypes 1.9.81 (26-Apr-2018)* NOTE: this version is not binary compatible with previous versions.

- ListEx: add CompareMethod argument to IndexOf method;
- Update documentation;
- Fix test application code.

----------


## hwoarang

*FTypes 1.9.82 (02-Aug-2018)* NOTE: this version is not binary compatible with previous versions.

- ListEx: implement binary search for IndexOf property (array should be sorted), extend Sorted property values range;
- Update documentation.

----------


## hwoarang

*FTypes 1.9.83 (26-Aug-2018)*

- ListEx: optimize Distinct method to perform sorting only if needed, reverse sorting flag in Reverse method;
- Update documentation.

----------


## hwoarang

*FTypes 1.9.84 (03-Sep-2018)* NOTE: this version is not binary compatible with previous versions.

- ListEx: add UsePartialMatchForStrings parameter to IndexOf property;
- Update documentation.

----------


## hwoarang

*FTypes 1.9.85 (22-Sep-2018)* NOTE: this version is not binary compatible with previous versions.

- TypesInterface: add Size property and modify all classes implementations appropriately;
- Update documentation.

----------


## hwoarang

*FTypes 1.9.86 (22-Dec-2018)*

- StringEx: add IsEmptyOrWhiteSpace property;
- StringEx: optimize TrimL/TrimR methods performance;
- Update documentation.

----------


## hwoarang

*FTypes 1.9.87 (31-Dec-2018)*

- ArrayEx & ListEx: fix inability to store objects;
- Update documentation.

----------


## hwoarang

*FTypes 1.9.88 (20-Jan-2019)*

- ArrayEx: fix indexes conversion mistake that caused Item, ToList and ToString to work incorrectly with multidimensional arrays;
- ListEx: fix wrong Sorted property update in case when StartIndex or EndIndex argument is used;
- Update documentation.

----------


## hwoarang

*FTypes 1.9.89 (02-Jun-2019)*

- ListEx: fix inability to store inner arrays;
- Update documentation.

----------


## hwoarang

*FTypes 1.9.90 (04-Jul-2019)*

- ArrayEx: defaults Sorted flag when Item is set, fix incorrect AddRange behavior;
- ListEx: inherit base functionality from ArrayEx class;
- Update documentation.

----------


## hwoarang

*FTypes 1.9.91 (07-Jul-2019)*

- ArrayEx & ListEx: fix excess item creation when Add method failed internally;
- ArrayEx: fix wrong cut of last delimiter in ToString method;
- ListEx: fix wrong Sorted property value after Distinct method successful call.

----------


## hwoarang

*FTypes 1.9.92 (08-Jul-2019)*

- Common.ToNumber: fix incorrect parse result in case of only one numeric char exist in string.

----------


## hwoarang

*FTypes 1.9.93 (16-Jul-2019)*

- StringEx: add Contains property;
- Update documentation.

----------


## hwoarang

*FTypes 2.0.0 (8-Nov-2019)* NOTE: this version is not binary compatible with previous versions.

- Implement IFTypeConvertible interface;
- DateTimeEx: fix incorrectly working Add* methods;
- Update documentation.

----------


## loquat

https://bitbucket.org/hwoarang84/shared/
this repo is out of access now

----------


## hwoarang

> https://bitbucket.org/hwoarang84/shared/
> this repo is out of access now


Hi. I've released an updated library *2.1.0*. See all related info at https://bitbucket.org/hwoarang84/vbtypes/wiki/Home.

Major updates:
- Redesigned interfaces, refactored code
- Name of library is now *VBTypes*
- All shared modules are available as git submodules
- Test project inside solution requires addin installation to run (see https://bitbucket.org/hwoarang84/vbt...i/Installation)

----------


## xiaoyao

can't find Ext\VBCore\Comparer.bas

----------


## hwoarang

> can't find Ext\VBCore\Comparer.bas


Please, read documentation. Mentioned  module as well as others is located in external project. You need to get it as git submodule command before opening solution

----------


## hwoarang

*VBTypes 2.1.1 (12-Apr-2021)*

- DateTimeEx: fix properties behavior
- Minor performance adjustments

----------


## SearchingDataOnly

If StringEx can implement/simulate the functionality of JavaScript String object, it will be a very valuable thing.

----------


## hwoarang

*VBTypes 2.1.2 (8-Aug-2021)*

- DateTimeEx: add HasDatePortion, HasTimePortion properties and AddQuarters method;
- DateTimeEx: fix interval add methods;
- Enhance tests

----------


## smileyoufu

Im very sorry, but I cant access the link below. There may be a firewall on the network. Could you please upload the file "master.zip" to the attachment of this post for the convenience of others



https://bitbucket.org/hwoarang84/vbtypes/get/master.zip

----------


## hwoarang

> Im very sorry, but I cant access the link below. There may be a firewall on the network. Could you please upload the file "master.zip" to the attachment of this post for the convenience of others
> 
> 
> 
> https://bitbucket.org/hwoarang84/vbtypes/get/master.zip


Use this link https://bitbucket.org/hwoarang84/vbtypes/get/main.zip

----------


## SearchingDataOnly

Great. It is recommended to add *SortCallback* feature to ListEx.*Sort*.

----------


## smileyoufu

thank you very much!
It can be downloaded, but the bas file is missing. Is my method wrong?

Attachment 182067

Attachment 182068

Attachment 182069

A total of 8 bas files are missing

----------


## hwoarang

> thank you very much!
> It can be downloaded, but the bas file is missing. Is my method wrong?
> 
> Attachment 182067
> 
> Attachment 182068
> 
> Attachment 182069
> 
> A total of 8 bas files are missing


Please, read documentation - https://bitbucket.org/hwoarang84/vbtypes/wiki/Home. You need to execute _git submodule update --progress --init --force --remote -- "Ext/vbCore_ since this project depends on another repository where shared BAS files are located.
So generally, you should not just download ZIP with main branch content, but use GIT to clone repository to your machine - git clone https://hwoarang84@bitbucket.org/hwoarang84/vbtypes.git and then download submodule(s) with Git command above.

----------


## smileyoufu

Thank you for replying to me in time
I'm sorry to trouble you. You cant access Google-related URLs in "Tianchao", and bitbucket.org cannot be accessed normally, but you can access GetHub. You can search for "FTypes" (https://github.com/hwoarang84/FTypes) on GetHub, but it is very Unfortunately, the visit has lost its effect. I am ready to abandon the study of this project because I cannot obtain effective resources.
Thank you for your help!

----------


## hwoarang

> Thank you for replying to me in time
> I'm sorry to trouble you. You cant access Google-related URLs in "Tianchao", and bitbucket.org cannot be accessed normally, but you can access GetHub. You can search for "FTypes" (https://github.com/hwoarang84/FTypes) on GetHub, but it is very Unfortunately, the visit has lost its effect. I am ready to abandon the study of this project because I cannot obtain effective resources.
> Thank you for your help!


What google related links? Project on GitHub is obsolete and I'm not going to support it there in anyway. You have all needed URLs in topic header and duplicates in last few messages. I cant influence on your local internet connection troubles. And I do not know your aims and what "study" means.

----------


## hwoarang

*VBTypes 2.1.3 (8-Jan-2023)*

- ArrayEx: fix issue when Sorted flag was not reset on array termination;
- Add Decrement and Increment methods to all numeric types.

----------


## hwoarang

*VBTypes 2.1.4 (15-Jan-2023)*

- ListEx: add First and Last properties, add Concat method.

----------

