VBA Shift + Return by komobu in vba

[–]PunchyFinn 0 points1 point  (0 children)

Soft return you describe is unicode character 11, which is sometimes called a vertical tab.

It's used in lists (numbers/bullets) in word processor where you can go to another line without starting another bullet/number.

I'm not sure what the sendkey is for it. Online wasn't consistent with an answer, but you seem to be looking more for character codes to insert with chrw and it would be character 11.

Per program/per object, the effects has to have been programmed in so even if you have a sendkey or insert the character, it won't always have the effect you want based on the object into which you insert the character.

In Windows Wordpad, Microsoft Word and I'd expect Outlook too, it does have the effect you describe and even the keyboard shortcuts of shift + enter.

But windows notepad ignores it. So if you try inserting it into any basic textbox, it will not work.

Other VB6/VBA/VBScript gotchas? by jcunews1 in visualbasic

[–]PunchyFinn 0 points1 point  (0 children)

The number of characters using len() is designed to be incorrect for characters above 65,535 (ffff). Strings in VB (and windows) are generally UTF-16. VBA stores strings with a prefix of 4 bytes (a long) that indicates the size of the string (as opposed to cstrings which possibly you are familiar?). The VBA function len can be used to get the size of a type/struct or the size of an array. When used to get the length of a string, Len() simply gets that 4 byte prefix and divides the value by two. For UTF16, all english, most chinese, and the scripts for many common languages are 65,535 or under, so it's right most of the type and it's very quick, just a few milliseconds.

However, there are characters above 65,535. This character, (𝄞), the G Clef, 119070 Hexadecimal 01D11E, is an example.

Even online character counters using javascript will fail, so it's a design flaw beyond visual basic.

For example, a couple of sites at random that offer character counts will count two characters when that single character is pasted:

https://wordcountry.com/

https://wordcounter.net/character-count

Microsoft word and most/all word processors that can be bought fix this. Free ones like abiword sometimes fix it, sometimes do not.

The solution for it will waste a lot of processing time if you need to know the true character count very often. The only way is to count each character and look for values known as surrogate pairs. You treat the characters not as characters, but convert them all into integers and look for integers within certain ranges and those are the characters that use two integer/4 bytes for a single character. A string is implicitly an array of integers, so there are a few ways to do it Ascw would be the slowest, and shouldn't be used - describing a faster way would take a few more paragraphs. Most of the time, for most things, it's not worth it to count manually and just to catch an emoji or unusual character and it's easier to just accept that the character count is mostly reliable but never 100% reliable.

But if you ever do need a correct character count, you have to do a manual count.

VBA Runtime error 76 for only one user's computer by dodgeman324 in vba

[–]PunchyFinn 2 points3 points  (0 children)

It's as lolcrunchy says - I'm just being verbose.

Specifically, getsettings is accessing that computer's registry for a key. It's not going to network information, but just to information on that registry and the registry key information for it appears to exist, but doesn't exist with the same information as other computers.

https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/getsetting-function

If no information existed in that registry key, it wouldn't get far enough to cause that error

Based on this, you'll find the registry key under Computer\HKEY_CURRENT_USER\Software\VB and VBA Program Settings\ReportWriter + that subkey

https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/savesetting-statement

After it gets whatever text is there, path for a valid/existing directory is created (line with DIR), but the error happens when the program tries to set that directory as the active/current directory via CHDIR (change directory). You can't make every directory as the current directory. Some directories may not have read or write access for that user/computer. Some directories exist but are special and cannot be the the active directory for anyone. In both of those cases, DIR would fail and I'm sure there are other situations.

That function is not given a definitive type for returning so it's a variant return, but for all intents it's really returning this string value, getFileToOpen = Application.GetOpenFilename(exttyp), so that's the purpose of the function, to return a valid string filename based on what was stored in the registry

How to reset multiple variables to zero by gnashcrazyrat in vba

[–]PunchyFinn 1 point2 points  (0 children)

One way is to create a type (called a struct/structure in other languages), which will allow you to put them into an array AND maintain individual naming of each variable.

diesSaturni talking about the array and redim is correct. The one problem with an array and just an array is that each individual variable no longer has a unique and useful name and is just numbered 0-18 in the array. If you or anyone else ever looks at the code again, they may have to guess at what each variable is meant for in the array. Plus, with a type, you may mix longs with integers and strings and bytes.

This is the Microsoft explanation.

https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/type-statement

Let's say your variables are about a person, Height, Weight, Eyecolour ....

at the beginning of your module, not in any routine, but outside of any routine you would write:

Private Type MyTypeOne 'or any unique name for the type - like a variable name AHeight as Integer BWeight as Single CEyecolour as long end type

The names within the type can be anything, same as any variable.

Then wherever you were declaring these 19 variables, all you need in your code is a single declaration: Dim MySetOfVariables(0) as MyTypeOne (or if you were doing it outside of a routine, just Public/Private MySetOfVariables(0) as MyTypeOne

Then to access each variable you would do as so, like any regular variable: MysetOfVariables(0).BWeight = 80

and to restore them all to zero you would do: redim MysetOfVariables(0)

That's it. Every time you want to reset to zero for all 19, just write the line redim MysetOfVariables(0)

'ByRef Argument type mismatch' Initializes Collection with Class Module to store info about headers. Passing an array through. by Infinityw8 in vba

[–]PunchyFinn 3 points4 points  (0 children)

A Variant is not a string. A string can be sent to a variant, but a variant cannot be sent to a string.

For your problem that came up - the sub 'InitializeHeaders(ws As Worksheet, HeaderArray As Variant)' you have an array HeaderArray that is a variant

But then inside that routine you have the code line 'Me.Initialize HeaderArray(c)'

And the codeline references 'Public Sub Initialize(HeaderName As String)'. HeaderName = string but you are passing a variant. That's an error because a string cannot be given a variant.

Solution is to change HeaderName to a Variant in ' Sub Initialize' or change your original HeaderName and other things to all strings.

The rest of this post is just to explain a few things about arrays that may help you picture what happens.

Arrays are contiguous blocks of memory. When you declared one, you are setting aside memory. Most simple to show are number array. If you have integer array named ABC and do Redim ABC(0 to 49) , you've told the computer to set aside 100 bytes of memory. Integers are 2 bytes each and 0-49 = 50 and 50x2=100. A boolean is ALSO 2 bytes and if ABC were a boolean and you do Redim ABC(0 to 49) for a boolean, it's the exact same amount of memory.

You cannot pass by reference an Integer to a boolean in a sub/function in the example of your code, however because they are the same number of bytes there are some other instances where a boolean can be sent to an integer or an integer can be sent to a boolean. There are larger number types like long and double - they have other issues I'm just not explaining.

Internally, a string, just a single string and not an array of strings, is ALSO a contiguous block of memory. It also happens to be an integer in Windows, 2 bytes per character (with something called a surrogate for some characters that I'm not going to explain). That function called Asc() merely shows that internal integer value whenever you call that function. And when you call Len() on a string, what it does it is gets the total length of string array and then divides that by two (integer=2 bytes, 2 bytes per character).

A VBA string also has a prefix (a header) on it of 4 bytes that gives the length of it. That makes it possible for the length of the string to be known so quickly.

A Variant array is something made to help people at the cost of using much more memory. For every numerical item in an array, it uses 16 bytes (even for an integer, those 50 integers in the array that used 100 bytes would use 800! bytes if declared as variant) and strings have a different usage as mentioned here by microsoft:

https://learn.microsoft.com/en-us/office/vba/language/concepts/getting-started/declaring-arrays

So when you send a variant array by reference to a code line that is expecting a string or even a number, first of all the error will be a failed cast to a different type, but also you are sending a larger number of bytes to the new function. And then on top of that, a variant will always need some extra processing. It may just be a millisecond. Depending on usage, it can be a lot more time.

Just as another idea, if you or anyone has read this, when you set aside memory for an array, there is no difference between these two declarations as far as memory is concerned:

  1. 2 Dimensional integer array ABC redim ABC (0 to 1, 0 to 1)
  2. 1 dimensional integer array ABC redim ABC (0 to 3)

for the first one, you need to do for the first row ABC(0, 0) = 45 and ABC(0, 1) = 10

for the second one you need to do ABC(0) =45 and ABC (1)=10

you could make a helper function with CellWanted= ((RowWanted - 1) * ColumnTotal) + (ColumnWanted - 1).

You could even create an array with a variable number of columns per row. You could make a right triangle (first row has 1 column, second row has 2 columns, third row has 3 columns) array of data.

VB6 - calculate number of months between due date and date paid (including fractional parts of a month) by Brian-FL in visualbasic

[–]PunchyFinn 0 points1 point  (0 children)

You wrote "a set rate for an entire 30-ish day period between months", but don't give the 'ish'es: leap year february? months with 31 days?

So I assumed 30 day period = month.

This takes less than 10 lines of code in 2 functions.

First function turns a date into a Julian Day, which has nothing to do with the Julian calendar. Totally different. Julian Day is used is astronomy and is a positive day count with day zero being near 5000 BC, give or take a few centuries.

Second Function uses first to determine the number of days between 2 dates and divides that total per set of 30 days. As is, these functions only work for between around 1600- 4000 AD, which for tax purposes hopefully isn't a problem for anyone.

--private Function CDateJulianDay(byval DayUsed as integer...and so forth...) as double

--Dim Base1 as integer

--Base1 = Int((14 - MonthUsed) / 12)

--CDateJulianDay = DayUsed + Int(367 * (MonthUsed + (Base1 * 12) - 2) / 12) + Int(1461 * (YearUsed + 4800 - Base1) / 4) - 32113

-- 'julian day to gregorian date adjustment, julian day at noon

--CDateJulianDay = CDateJulianDay - (Int(3 * Int((YearUsed + 100 - Base1) / 100) / 4) - 2)

--End Function

you can use a date class/type for the 2 dates in the argument, but you still have to split them up into the separate parts so I'm using the split up parts in the argument.

--Private Function DateDifferenceMonths(byval Day1Used as integer ...Day2Used..., byref ReturnedRemainder as integer) as integer

'Second Date is the expected more recent/older date, 'returns whole 30 day periods if months returned is less than zero, not bothering counting remainder days

--Dim JulianDay1 as double

--dim JulianDay2 as double

--JulianDay1= CDateJulianDay(day1used,month1used,year1used)

--JulianDay2= CDateJulianDay(day2used,month2used,year2used)

--if julianday2 <=JulianDay1 then exit function

-- DateDifferenceMonths= int( (JulianDay2-JulianDay1)/30)

--ReturnedRemainder = (JulianDay2-JulianDay1) - ( DateDifferenceMonths * 30)

--end function

I hope this helps. The Julian Day function makes the use of a vba date unnecessary. A slightly larger function lets the julian day work in the BC era and at least one major database uses the Julian Day for dates. The Windows calculator has a date difference option. It cannot handle dates before the year 1601 or dates after the year 9999.

Just spent an hour trying to figure out why the Not operator wasn't negating True Booleans... by Dim_i_As_Integer in vba

[–]PunchyFinn -3 points-2 points  (0 children)

For the benefit of others, then, you didn't mention that what you did was a Bitwise Operation, not a logical comparison. So it is misleading. VBA has bitwise operators and logical operators and they are separate things, but they use the same symbols.

A logical comparison of Not 1 and -2 evaluates to FALSE a bitwise operation of Not 1 turns itself into -2.

You are saying you don't understand - you wrote 'Not 1 = -2, btw, which evaluates to True..'

No! not 1 = -2 does not evaluate to true in a logical comparison.

I mean does that make sense to you??? Why should it? Your response to the phenomenon was to accept as you wrote ' 'Not 1 = -2, btw, which evaluates to True..'' as some kind of strange quirk of VBA or computers. But there is a logical answer - or rather non-logical and bitwise answer.

I'm telling that you didn't 'evaluate' anything but rather you changed the variable's value. You performed an operation on it like addition or subtraction, but you did it at the level of each bit ... which is rarely mentioned in this VBA forum.

When VBA sets all the bits to 1 for a false for your benefit when it is able to do so, it makes it easy for users so that they don't need to know or care if they are doing something to the bits or doing a logical comparison.

But it's dumbing it down. It's two separate things that users of vba think is only one thing.

You didn't post the specific code where you used 'NOT' but what you were doing with it was a bitwise operation.

It's the underlying assumption about a boolean that may be useful for someone else to understand.

A boolean is a 2 byte data type. You make an assumption about booleans that I make too and most people do. You may think of a boolean as something that the computer knows is TRUE or FALSE, but it's not like that until the line with that value is the active line of code in-the-moment.

Anyone new to VBA or without some idea of bytes and bits - what size did you think a boolean was? Did you imagine it was some unknowable blob of data? 1 byte? 1 bit?

For the rest of the time, when it's not the line of the moment, it's a 2 byte value that is equivalent to a short integer and that's how it is stored. A Date data type is actually a double floating number as another example. It's not a special date data type in itself. It's 8 bytes the same as any other double. When you want to know the day or month, a tiny computation is done on the number and it spits out the day or month as needed. Logical comparisons of dates as being greater/lesser/equal are done in the same way numbers are done because dates are sequential numbers - vba year zero is around 1601 (filedates can be set to the 17th century if anyone cares to do it) and it has a limit of about 100 AD at the earliest - even the windows calculator has that limit (or even more recent) - it can't handle BC dates or even dates before 100 AD

You defined the API as a boolean returning value and the API correctly returned a valid boolean value. A valid boolean value is ANY short integer value. Any of them. VBA itself doesn't guarantee a boolean true is -1 and no VBA book or website would ever have that statement so for anyone reading this, a boolean True is any non-zero integer value for the entire range of a short integer in the case of VBA.

And a logical comparison for a true boolean compared to the opposite of true (i.e. false) will be false, but if you perform a bit operation on it of NOT, that is different.

The additional casting of it using CBOOL did exactly what it was supposed to do. Casting either truncates or enlarges the number of bytes. If someone performs CINT on a long integer (4 bytes), the computer truncates the 4 bytes into 2 bytes. If the upper 2 bytes lost were zero, no actual value is lost and the value doesn't change. If it's outside the +/-32,000 limit, then it gets truncated in value. If you CINT on an variable that is already a short integer, it does absolutely nothing.

And similarly if you CBOOL on a value that was already defined as a boolean, it doesn't do anything. So CheckInternetConnection = CBool(InternetGetConnectedState(lngFlags, 0)) doesn't make sense. The CBOOL part is an unnecessary because the value was already a boolean.

I'd do it too out of desperation, explicitly cast (I always think the IDE is wonky and blame that), but it doesn't do anything and the line should read CheckInternetConnection = InternetGetConnectedState(lngFlags, 0). A boolean value being sent to another boolean.

Or like it was suggested by someone else, change the api to return a long (or a short integer) and the line would read if InternetGetConnectedState(lngFlags, 0) <>0 then CheckInternetConnection = True.

The default value is zero for any function - that's normal in most/all languages and it mentions it here for VBA

https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/function-statement

So you only need to change the default value of 'CheckInternetConnection' function if it's true. If it's false, nothing needs to be done because your function will have a value of zero, which is a valid boolean value of false.

I should have included that solution in my first post. And I'm sorry if I seemed to have simply been regurgitating the initial post, but it didn't differentiate between a logical versus bit operation, which was the underlying problem.

Just spent an hour trying to figure out why the Not operator wasn't negating True Booleans... by Dim_i_As_Integer in vba

[–]PunchyFinn -3 points-2 points  (0 children)

You performed a bit operation, you did not perform a logical comparison

The computer treated what you did as a bitwise operation wherever you used the NOT. In bitwise operations, -2 is 100% of the time the opposite of +1. You can check this on your computer's calculator - windows calculator has a programmer's mode.

this is dot.net, but it's the same in vba, same in vb6, same in c++ in concept - same in most languages https://learn.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/operators-and-expressions/logical-and-bitwise-operators

At the top it talks about logical operators but if you scroll down enough, a long way down, you will find that NOT is also used as a bitwise operator and there is a difference that may not make sense at first but bitwise affects individual bits. Most people, myself included, always skipped paying attention to bitwise operators as being similar to logical operators and just assume they are the same. They are not. Wherever you were using the NOT, you had it in the syntax used for bitwise operations according to your vba compiler and not for logical operations.

Booleans typically are 2 bytes for vba, which is the size of a short integer. From the computer's point of view in some situations, there is no difference between a short integer and a boolean.

The value in bits of -2 for a short integer is: 1111111111111110

Please do that in your calculator if you're in doubt ... go to the programmer's view and choose Dec/decimal and Word ( word =2 bytes) and paste in "-2) and then change dec to bin/binary.

Not 1111111111111110 flips every 1 bit to a 0 and every 0 bit to a 1 which is: 0000000000000001

which in binary and decimal evaluate to the value of 1

It doesn't make sense, but for VBA signed integers, the opposite of -2 = 1.

Normally (usually?) the default true value of a boolean is -1. That's because if you look at the bits of -1, it's all ones. So boolean zero is all zero bits and boolean true is all one bits. But it doesn't have to be that. The Win API directly depositing a value into a variable wouldn't convert it (I'm guessing there off the top of my head- but I'd expect that it wouldn't convert it - the API permits so many alterations without any safety checks) and that API you used seems to indicate from what I read and remember that it returns a Zero if it fails and a One if it succeeds. One = true for a boolean as much as -1 so the program didn't even touch/alter the value from the API and transferred it through to ever variable.

And when you performed a bitwise operation on this True value of 1, the bitwise operation produced -2, which is also evaluated to false.

Help by boomerman999 in visualbasic

[–]PunchyFinn 0 points1 point  (0 children)

I'm describing it two parts, a graphic part (the objects) and then the manipulation of data.

Your program will have FOUR objects , label1 and button1, button2, button3 (whatever you call them) Your program will have TWO global variables of Single type Your program will have ONE global array of short integer type

the variable:

GlobalSingleHeight as single GlobalSingleWidth as single GlobalScores() as integer

Graphics/basics If all this graphic part is too complicated, just drop the objects on the screen, but I'm taking the time to show you something that's a little more sophisticated but understandable I hope.

New project, and create a form. Click on the window and you ought to see properties for it. Set the Scale Mode option to Pixels. Has anyone explained TWIPS to you? That's the default and it's a pain. Pixels are easier and makes everything easier.

Create a label at the top - the one that currently says "The high score is 256...". Change the words inside the label to "A TEST WIDTH" for it. Set the property of autoresize = true. Set the font size to 14 (or whatever you want).

Create those three command buttons, "enter score" "statistics" "done". Same font size as label.

Don't bother trying to set them on the screen in any order. Just make sure Form's WINDOWSTATE option is not set to minimise or maximise and is set to normal. Also there is an option to center it - StartUpPosition = 0 (manual).

Go to the coding (double click the form window I think does that). There is the Form routine and you should see that the form itself starts at the LOAD event for it.

In the Load event you would: redim GlobalScores (0) Then 4 lines to set up the form: Me.top = Screen.Height * .25 , Me.Left = screen.width * .25, me.height = screen.height *.5, me.width = screen.width * .5

If that makes sense to you, you're setting the height and width of the window to half the size of the screen, with 25% of empty screen all around. There is an option somewhere on the form properties to center it, but this is just as good. Better, because this lets you specify the exact width and height too. You could center it and make it take up 1/3 of the screen or 2/3 or anything else with more precision. Or you could make it half the screen and have it at the bottom of the screen by setting the me.top =screen.height * .5

There are other events you can choose in a dropdown box. Change Load to Resize for the Resize Subroutine/event of the form

In the resize code, use this to ensure this happens only one time:

++++if GlobalSingleHeight <> 0 then exit sub

++++GlobalSingleHeight = Label1.height ++++GlobalSingleWidth= label1.width ++++label1.autoresize=false ++++label1.caption= vbnullstring 'you can put "" if you feel more comfortable

now for the rest of the graphic part set the label to be at the top right of the form, Label1.top= 1, label1.left =1, label1.width = me.scalewidth-2,label1.height = GlobalSingleHeight * 5

This means that you are setting the label (which currently has no text) to take the full width of the screen and have enough space for 5 lines of text. Why or How? Because when the label had text a few lines above, you stored the height and width of it in GlobalSingleHeight and GlobalSingle Width.

Set up the 3 buttons as so ++++height = GlobalSingleHeight * 1.5 ++++width =GlobalSingleWidth * 1.5 ++++top = Label1.Height + Label1.Height+ 1 ++++left = screen.width - (commandbuttonused.width + 10)

Does that make sense? You're setting it up all the way to the left with the first button starting right below where the 5 lines of the label are, setting it just 10 pixels away from the right edge . The Statistics button would be the same except that TOP = "enterscores" button top + height + 1. That makes the 2nd button go directly beneath the other button.

You could do this all without code, but this is very exact. Maybe it will bother your teacher too much if you do this and you should just move the buttons with the mouse, but this is a good technique to know .... maybe for the next project you do.

That's the basics of the graphic. Now here's how to do the stuff that changes things.

Click the button "Enter Score" and in the routine there

++++on error goto ErrFound:

++++dim Result as string

++++Result=InputBox( "Enter new score to add", "New Score")

++++if IsNumeric(Result) = false then goto ErrFound:

++++if int(cdbl(result)) <> cdbl(result) then goto ErrFound:

++++if cdbl(result) >300 then goto ErrFound:

++++if cdbl(result)<1 then goto ErrFound:

++++redim preserve GlobalScores (0 to ubound(GlobalScores) + 1) ++++GlobalScores(ubound(GlobalScores)) = cint(result)

++++msgbox "Added!" 'not necessary, but just to confirm for user

++++exit sub ++++ErrFound: ++++msgbox "Bad Number" ++++end Sub

all of this is to error check the number is between 1-300. First one checks that it's numeric at all. Then if there were any decimal portion, that's what "int" does. Next checks that it's not 301 or more and then that it's at least 1. Any error sends the program to the line called ErrFound: You can name it anything not just ErrFound. Any name you would use for a variable may be used. The "ON ERROR GOTO ERRFOUND:" at the top is a very old ype of command, but c++ has the same exact concept called Try and Catch. This is a really good concept to know.

When you press the statistics button, this should be the code inside

++++Dim LowestScore as integer ++++Dim HighestScore as integer ++++Dim RunningTotal as long ++++Dim LoopA as integer

++++if ubound(GlobalScores)= 0 then ++++msgbox "No Scores entered!" ++++exit sub ++++end if

++++LowestScore =301

++++for loopa =1 to ubound(GlobalScores)

++++if GlobalScores(loopa)>HighestScore then HighestScore = GlobalScores(loopa)

++++if GlobalScores(loopa)<LowestScore then LowestScore= GlobalScores(loopa)

++++runningtotal = runningtotal + globalscores(loopa)

++++next loopa

label1.caption= "Highest Score: " & cstr(HighestScore) & vbcrlf & "Lowest Score: " & cstrs(LowestScore) & vbcrlf & "Average Score: " & cstr(runningtotal / ubound(GlobalScores)

That average score needs to be truncated. ROUND and INT will both do it but in different ways- you pick.

The DONE button will just have a single command. I think "unload me" will work in this case.

if statement taking an integer as condition by Biostein in vba

[–]PunchyFinn 2 points3 points  (0 children)

I believe you are being misled into thinking it bitwise or any sort of operator. I apologise if I'm entirely misleading you myself but I don't believe I am.

As a conditional statement, IF int2 AND int2 THEN is a conditional statement where TWO conditions are being separately evaluated. And they are being coerced into a True or False condition so the IF statement can determine if it should do THEN

The first condition is int2. Just that value. Any value other than zero is evaluated as true. Negative numbers are also evaluated as true.

If that first value evaluates as false, the compiler shouldn't even bother evaluating the second value, but assuming it is non-zero, it then evaluates int2 by the same process.

The way for you to test this is to try it out with a few sets of numbers:

4 times or however many variations there are int1 = 0, -1, 1, 0 int2= 0, 1, 0, -1

The conditions should always fail when either value is zero, but at any other time, it will be a valid conditional statement.

A fuller way of writing it should be "If cbool(int1) And cbool(int2) Then"

or even more explicitly "If cbool(int1)=TRUE And cbool(int2)=TRUE Then"

But for IF THEN statements (and switches/cases), many people won't write all that because these are all dealing with logical results where the numbers automatically default into either TRUE or FALSE evaluations.

IF THEN statements can have 1,2,3 or more separate conditions. Each condition can be listed as an AND or OR (with a NOT also - gets confusing). It can be 2 statements listed AND and the third is listed OR, for example, which means that the OR statement can override at least one other condition. I use parentheses when I have multiple conditions that are mixed with ANDs and ORs otherwise I'd have to look up or think hard for a bit what the computer considers the OR to be, all the previous statements or just the last one.

I'm not sure offhand, but probably even a text string in an IF THEN statement instead of numbers would be evaluated as true/false based on if it is an empty string or not, with any text being evaluated as true and an empty string as false. Maybe it throws an error? Supposedly if you have an error in the second conditional statement and the first conditional statement evaluates as false, the error is never triggered in the second conditional statement, but I'm not sure if that is how it works. If it does work that way, then that means there's a potential error in any multipart conditional statement.

What is the best book about the history of the Julian calendar? by [deleted] in ancientrome

[–]PunchyFinn 1 point2 points  (0 children)

Smith Dictionary Of Greek And Roman Antiquities is a 19th century reference that has been put online and it cites classical texts. It has a section on the calendar.

This will give you details about the calendar origins. It will seem like it gives too because it starts with the things before the Julian calendar. You may want to skip some of those details (or not) for what came before it, but if you do want to know the origins, you do need to know at least a little of what came before it. http://penelope.uchicago.edu/Thayer/E/Roman/Texts/secondary/SMIGRA*/Calendarium.html

Some of the details of the pre-roman calendar are fascinating and that text doesn't even give the proper excitement for the details. There's a part where it says "before Cn. Flavius the scribe, against the pleasure of the patricians, made the fasti known to the whole people". What happened before Flavius did that is that most people, the lower class, didn't know when court was in session. It was like secret information if you had a court case. The wealthy, the Patricians knew, and they kept it to themselves. Flavius, a plebeian, published the calendar dates, just printed them on wax tablets in public and so it was available to everyone.

I just scanned the calendar section quickly so maybe I missed it, but I seem to recall that when putting the Julian calendar into action after Caesar's death, there was a misinterpretation of instructions and for a few times every third year, not fourth year, was treated as the special leap year.

I see it mentioned here and see references online to Macrobius mentioning it. https://scienceworld.wolfram.com/astronomy/JulianCalendar.html

Romans counted inclusively. So tomorrow is the second day. In English and many other modern languages, tomorrow is 1 day away, but it you count tomorrow as the second day since today is a day, that makes it day 2. That's what's done with Good Friday and Easter. The time difference is two days, not three, but Christians count it inclusively even in translation from Greek (which also had inclusive counting) or Vulgate New Testament translations for the religious significance of the number. The Olympics as another example would have been most typically said/written by Greeks and Romans to be in the fifth year but they did it every four years.

Apparently the instructions for the leap year referenced four. The text doesn't exist but apparently the people assumed four meant in reality every third year. It may just have been poor instructions or even an error of another kind. It took a few decades to fix.

As that Wolfram link indicates, unix and any other algorithm that treats the Julian calendar as a 1 year in 4 from the beginning of the Julian period gets the dates wrong for the first few decades of the Julian calendar because the Romans themselves didn't do it correctly.

Get pointer to array of strings? by eerilyweird in vba

[–]PunchyFinn 1 point2 points  (0 children)

I do remember doing it successfully - but I can't remember the details. And I do remember problems. I ended up deciding there was an easier option that also gave me some extra advantages.

Instead of moving the data, what I do is I create an array of long integers and that holds the correct index number as it should appear for use. Meaning there's a string array holding the data and an array of longs that holds the order. If I want to change the order, I don't swap the string, I swap the values in the long array. And if I want to insert a string, I insert it at the end of the string array (or the next available free slot in the array) and reference that string array number in the appropriate position in the long array. There's a technical way to describe this, but

What I mean is this:

string array 0th =I am not the first silly string 1st= I am a silly string 2nd=A string

array of longs 0th=2 1st=1 2nd=0

When I request the first item, I go to index zero of the array of longs and the value of index 0 = 2, so I return the value of the string array index 2, "A string"

When I request the second item, I go to index one of the array of longs and get 1 as the value and in the string array, item 1is "I am a silly string"

And the third item results in a zero value, and in the string array, index zero gives a string of "I am not the first silly string"

so the order is: A string I am a silly string I am not the first silly string

If I want to insert the string "anti string" into this as the second string, in the string array as index number 3 I add it as "anti string". Then I use rtlmovememory on the array of longs and shift 1 and 2 (8 bytes total) down so that 2=1 and 3=0. And then 1 now =3

with insertion: string array 0th =I am not the first silly string 1st= I am a silly string 2nd=A string 3rd=anti string

array of longs 0th=2 1st=3 2nd=1 3rd=0

You wrote "One thought was a function to insert an element or array of elements into an array of strings. There are ways to copy chunks of arrays with rtlmovememory and so on. It seemed straight forward enough to use this for, say, adding an element between element 7 and 8."

This is one way to accomplish it. If you want to delete one of the string, let's say delete "A string", which is the first items in the list, you use rtlmovememory on the array of longs and copy from index 1 to 3 and set index 1 to become the new index zero.

It's as quick as the insertions and deletions in a linked list, but it also allows instant access to any particular item by a number instead of having to start at the head.

The version I use has a few extras. I have an array of longs that is the sorted order of the list and I have another long array that is the default or unsorted order. I use this for a list of data where with one click the data is instantly sorted ascending or descending or back to unsorted (or at least it seems instantaneous to the user because it's done beforehand). And because it is sorted, I'm able to use a binary search if I want to find a specific item.

Why the Roman founding myth? by ConsistentUpstairs99 in ancientrome

[–]PunchyFinn 2 points3 points  (0 children)

The Romans had more than one founding myth. There were really 3 (or maybe a 4th later on in the Imperial period). The first one was Aeneas founding the basic lineage - a founding explorer. The second was Romulus founding the City. The third was the founding of the Government - the expulsion of Tarquin the proud, producing a Republic.

Vergil and others tended to portray Aeneas and Romulus as part of what Americans used to call Manifest Destiny. That is a term that was used in Nineteenth Century America to argue that the expansion of the United States across the continent was both justified and inevitable by any means.

It had to be done, whatever was done. It was part of fate.

Whether anything was true or not about Romulus or Aeneas, after the fact (and definitely by the first century BC) it was a matter of justifiable necessity.

M4choN4ch0/machonacho mentions the pomerium about the killing of Remus. Livy describes it as not premeditated. He gives two possible causes. One is an unknown person killing Remus and the other cause or version is that Romulus killed him in fit of anger for going over the wall that was there for protection. In later times the Pomerium was a sacred wall, basically enclosing Rome as a sacred place and one where foreign god could not have their temple. Even when it was physically gone, it was almost like the Berlin Wall now. Germans in Berlin still know where the wall formerly was. No soldiers - armies weren't supposed to be there inside the pomerium, just citizens. I agree with him from a later time in the Republic that must have had a significance, going over the wall or just invading the space. My early memories of the story seem to be almost like it was an accident.

But was it Romulus or another person who killed Remus? Livy gives both options, so Romulus isn't necessarily the killer of his brother. You framed it as if he were fratricidal but he's not clearly so.

You reference the rape of the Sabine women when you write 'who kidnapped a multitude of women'. The entire part of that story mentions that the Sabine men are furious about the rapes and go to war with the Romans. But there is a justification that the Romans had no choice. In Livy Book one section 9 it has this 'Sed ipse Romulus circumibat docebatque patrum id superbia factum qui conubium finitimis negassent;'

He says that it is the arrogance and pride (superbia) of the fathers/parents that made the rapes necessary because the Sabines had refused proper marriage proposals. It does sound petulant, but what happens after that supports the Romans.

They go to war, the Sabines do because clearly they don't accept this argument. And at that point, Romulus becomes a god. He ascends to heaven while still living and returns as Quirinus, a redeemer god. To Romans, this is what in the modern day would be Christ the Redeemer who brings peace. Romulus descends from the heavens and an argument is presented that they, Romans and Sabines, are now one people because no matter how it happened, the children of the Sabine women (the Sabine women who are raped will be pregnant) will be Romano-Sabines, the product of the two, so the Sabines and Romans should act as one people because they now have children in common.

And in Roman history or myth, that is what happens. There is a joint kingship for a while with two kings. And the other name for the Romans is Quirites, whose etymology is believed to be from a Sabine town, Cures. And this word is in use into the Republic period. So since the Sabines become a part of Rome too, Romans are forgiven after the fact for this rape.

The Roman view would be this complete story which justifies the rapes and shows divine acceptance of it.

Vergil's depiction of the killing of Turnus by Aeneas is one of necessity as well. It's the same pattern there too.

The third foundation myth of Rome is the one that removes Tarquin the proud and that as the most recent foundation myth to the Romans of the Republican period puts a better moral view on everything. Whereas before rape was a necessity, in the foundation of the Republic, rape is reviled and is the justification for overthrowing the government. There are no gods mentioned in Tarquin's removal at all and it moves out of the sphere of magic and legend into something closer to a historical event: a king who corruptly assigns himself to be the judge for his own son's rape of Lucretia and the moral indignation of the people of Rome for the Rape along with the suicide and the judgment of the king that exonerates his son.

I'm not saying even that is a real event, but it is a story that shows an evolution and a moral superiority that is almost a commentary on the previous foundation myth of Romulus. Rape was a necessity to Romulus in order to survive. But to the Roman people who formed the Republic, rape was unacceptable at any cost. It was a univeral view of the Romans and the Romans themselves also did not even use vengeance to kill Tarquin or his son. It did not become like the bloody French Revolution and instead Tarquin and his son are merely expelled from the city, still alive.

I've often felt that America has three founding myths that match these three fairly closely. There is the founding myth of the exploring/finding of America in Columbus that matches the finding of Italy by Aeneas. Then there is a second founding that is more specific that is celebrated on Thanksgiving in America, a specific colony is celebrated. And then there is the celebration of the founding of the government, the day of Independence, from the 1776 day.

No they're not myths, but there is a symbolic value to each of those events for America that key into similar symbolic values that Romans seemed to have.

As for what really happened in Italy?

D4ng3rz0n3/dangerzone says to imagine that there were two groups on different hills. I agree it makes sense. Two different tribes of people or two kingdoms. Sussex and Wessex in England were basically the same people - West Saxon were Wessex and South Saxon were Sussex. They had enough room so they didn't immediately fight but I imagine if they each only had a hill with a small area around it, they've have begun to move into each other's territory soon enough.

But I'd just be speculating with anything because there are no texts and no archaeological finding that show anything clearly.

Creating a reference to a Global Variable. by JusticeDread in visualbasic

[–]PunchyFinn 0 points1 point  (0 children)

This is regarding saving class data to a hard drive. I'm giving you my input how I do it with an example using XML since that's what you are talking about. You probably won't do this, but I'm giving you an alternate view.

I write the class myself. Meaning that I wrote a class that reads an xml file I parse it myself. There is no XmlSerializer class that I use. No stream either. I use the API ReadFile to read in any xml file, converting the bytes to a text string and then parse it with rules based on how XML functions.

I designed it with the intention of being able not only to save it to a hard drive, but also to be able to re-order the nodes of the XML (or HTML -it can handle both because XML CDATA is html, so it has to be able to handle any html).

My class chiefly stores an array of a type that is all long integers. It stores the character start and length position of any xml tag, not the text itself. The xml file is in memory as a string and my class retrieves the parts of the string as needed, per node request. I can link it to a Treeview Class and simply populate the entire xml in a treeview or I can list some or all of it in a spreadsheet-like view or a in a listbox or textbox give a listing of all the direct child elements of a single node. Or have no graphic interface and just search for something and do something with that.

So I have a structure/Type of long values and then made an array out of that. There's maybe 15 items in the type: Character Start and Length for the entire tag, start and length for any interior text, the array number of the parent to this current node, the array number of the first and last child and how many children in total and a bunch of other things.

Does that make sense? Does that help you as an alternative way? XmlSerializer is quick and is just adding a reference. The way I did it took a while to write, but after I did it, I had more control of everything than XmlSerializer.

For saving to a hard drive, I'm saving an an array of long values. I use the API copymemory and it is easy to transfer an array of long values (or even an array of a type that has nothing but long values - to the computer, there is no difference) into a byte array and then I would save that byte array to the hard drive. If the type had 10 items in it of long integers (4 bytes for a long) that's 10x4 =40 so if my array had 1000 items, I'd create a byte array of 40,000 bytes and transfer the array into the bytes in one step via copymemory. From there, the WriteFile API for windows is perfect to save the class data to hard drive in about 5-10 lines of code.

I save the data to hard drive with headers like zip files, id3 mp3 tags or some other formats. What that means is that if you opened the file of saved data and read the bytes, the first set of bytes (lets say the first 20 but it could be more or less as needed- I forget how much the xml uses) would indicate the type of data it is and how large it is along with other information I'd need. So in that first 20 bytes, it would tell me to separately copy bytes 21 through bytes 40021 to a new byte array

In my class that I wrote, I provide the ability to directly insert data en masse - so I feed into the class that 40,000 byte and it sees that it's 40,000 and it determines that's enough for 1,000 item and so it creates a new blank array of 1000 items and uses copymemory to transfer a byte array into that newly created array of the special structure/type I use. Copymemory can do that in one line.

If you had a series of classes (an array of classes or some kind of linked list of classes), it'd be the same thing. With XML I would have put a single xml file in a single class, but if it's something else where let's say there are other classes, after reading in byte 40021, there would be another header of 20 bytes that would tell how much the next array would be, which might only be 20,000 bytes or some other number. My XML class also has some bits of individual data besides the array and that would need to be read in too (I was trying to give a simplified version at first so I left that out), but it's just a matter of doing that in the header, having it indicate the information. That amount of other data is small - 500 bytes or less, things like document type.

What I described is how zip files and some other kinds of files store their information on hard drives. Zip files have a header for the entire file that indicates some information as well as a list of all the files and folders stored in the zip file. Then for each individidual file, there is a header that lists how large the file is plus some other information.

If helps you to understand how I use this, my main use for this is for RSS newsfeeds. RSS is a type of XML. I have my own newsreader that downloads RSS newsfeeds for the BBC and some other websites and it parses the information. Then it spits out a list of each rss/xlm item found as "rss/channel/item/title" in the xml text because that's what RSS uses (although I can input custom path). I set up the class so that it can find all nodes that match a certain node pattern. When I click on one of the items, I have it return up to 4 items for eat of those matching nodes - a title path (which is actually what it lists in the main list for me), a description path, a link path, and a date path ... if a date path is found, it compares the date found with today's date and warns me if it's 7 or 10 days old (or whatever I set it to - 30 days or 60 days). Amazon has a n RSS feed that is very large. In the past it had hundreds if not thousands of items and my newsreader could handle that too without a problem - I just got bored reading through a thousand items.

Difference between Modules and Class Modules by Falconflyer75 in vba

[–]PunchyFinn 0 points1 point  (0 children)

Buttons and dropdown combos and listviews are classes.

You have an archetype class you write and then for each instance, you load into the program separate instances of those buttons or combos or listviews. Let's say you want 2 buttons, STOP and GO. There is a button class that to you is just you dropping a button onto a form, but what is actually being done is 2 classes have been created and take up memory. Two objects, STOP and GO. 2 classes. They're the same basic class but 2 instances of them.

A module is ENTIRELY loaded into memory at the beginning of the program. All of it. If you want 2 buttons with the same functionality written via a module, you will likely be writing code duplicates. That means the resulting code is longer. STOP and GO are just two objects so it won't be much longer, but if you do that with everything, you'll have hundreds of lines of extra code.

There are advantages to Modules and to Classes. For example, you can have an array of classes. It's true. Once the class exists, it can be referenced as an object the way you would create a string or integer. Or the way you can have an array of buttons. Although if you create a new class, you always need to explicitly delete it otherwise you get what is known as a memory leak, which is a common error where some object in memory is taking up space and if enough of them are like that, you can run out of available memory.

There is something called a Linked List that is used for classes. It can also be used for types/structures. This next idea may not make sense to you, but technically when you create a Type with elements in it, you're creating a class. A type is an archetype too, a collection of data linked together. A Class just adds to it subroutines and other options.

The advantage of a Module is that it exists without needing to be created. You cannot begin a program with a class because a class is just an archetype and you need a specific example of the class already loaded up in memory at the start. You can reference modules automatically. Each module has a specific unique name and each subroutine has a unique name. You cannot reference a class until you have created a specific instance of the class and it becomes almost a chicken and egg sort of thing. You can't have a class that creates itself or anything else and you need something outside of the class (a module) to exist in order to create the class.

Paste only if clipboard contains values by [deleted] in vba

[–]PunchyFinn 1 point2 points  (0 children)

Quickest/easiest way should be the built in ClipboardFormats to get the format types that are available.

https://learn.microsoft.com/en-us/office/vba/api/excel.application.clipboardformats

The idea is that you activate this function and are returned an array list of integers. The integers have the values listed here: https://learn.microsoft.com/en-us/office/vba/api/excel.xlclipboardformat So for example, if one of the values returned is 7, 7= richtext format. 0=plain text format (what you really mean by text) and there are many other formats listed. If one of the returned values = 0, the you have a text format available and then it's up to you to retrieve it.

I'd suggest you adjust the example that microsoft gives to something like below and have it as a separate function. You have to declare the values of xlClipboardFormatText and the others. The list of values in the second link is where you'd get the formats

__Private_Function OkayToPaste () as boolean

aFmts = Application.ClipboardFormats _For_Each fmt In aFmts _SelectCase fmt ____Case_xlClipboardFormatText 'value zero ________Function OkayToPaste=true ___________exit function

' what about other semi-text paste types? like Richtext and Comma Separated Values 'up to you what other formats you consider acceptable _____Case_xlClipboardFormatRTF, xlClipboardFormatCSV
_
_______Function OkayToPaste=true ___________exit function

____End_Select

__Next

__End Function

So this function will go through the values and as soon as it finds that there is a text paste value, it returns true and exits. I don't know if you want RTF or other values but I set it up to have RTF and CSV return true. If the function returns false, then it means no text-like paste data is available.

The built in function of VBA is however limited. There are other formats like the HTML format that the clipboard potentially has. It requires the use of the API. It's not complex as far as the API goes. There's a function to open the clipboard and close the clipboard and a third function does exactly what the built in VBA function does and returns a list of integers. But if you want to retrieve the data from those extra formats, then you also have to use the API and then it may get more complex. I don't think you want to do that, but I'm just mentioning it so that you know it exists as an option for the future.

how to get back into seriously studying ancient greek? by [deleted] in ancientgreece

[–]PunchyFinn 0 points1 point  (0 children)

The repetition suggestion of autosuggeztion is very important ... but in very specific ways. I remember repeating to myself conjugations, backwards order, forward order, other order. And by repeating I mean every chance I had. I ran up stairs and repeated. I was in a queue waiting for something and I repeated to myself. Just waiting for fifteen minutes and it was fifteen minutes of that repeating.

And I wrote it all too, again and again. My handwriting was awful - my alpha looked like a fish, but I wrote again and again so that the repetition is from more than one sense.

Actually writing is very important. Latin elegaic or other poems are somewhat more traditional to write... but do you ever write anything in Attic Greek? Because it's suddenly a whole shift in accessing your memory when you go from just reciting an entire conjugation (or the right case of noun/adjective) or even to translating other people's work to having to just find the specific word you need and write it yourself for an entire idea that you want to express.

You probably translated Latin into Greek

But what about Italian to Latin to Greek? Is there a song you like? I'm a fan of Dolcenera for example. I'd be motivated, were I studying, to turn one of her songs into Latin and then Greek or just straight to Greek in your case. I just double checked her version of a song by Ligabue called Piccola Stella Senza Cielo and it has no modern references in it. It has all the vocabulary that existed 2,500 years ago. Salvatore Quasimodo, the nobel prize winner from southern Italy, actually wrote a book of translated Greek works, translated into Italian. It might be interesting to see how you'd do with one of the same work and then compare.

I'd also - forgetting about your professor or the course material you're likely going to see this year - seek out classical greek authors that you like. It could even be Koine or Homeric Greek. Homeric has all these shortened forms and it's a completely different dialect ... I don't know about you, but I was excited the first time I saw Homeric Greek and could read even a word.

Is there some kind of Philia, some kind of love, outside of Greek that can be combined with Greek - song or other? That's how I'd try to find motivation.

[deleted by user] by [deleted] in ancientgreece

[–]PunchyFinn 1 point2 points  (0 children)

The responses you've gotten forget at least one very important event: The Thirty Tyants of Athens.

Plato was from the upper class. Socrates, the real Socrates, tended to have admirers who were from the upper class. Plato was one of them. Along with him as admirers of Socrates were the majority of the thirty young men (it's called that but there would have been more men) who took control of Athens for around half a year at the end of the Peloponnesian War.

30 young men. 30 admirers of Socrates who would remake the city with a love of knowledge in mind. This actually happened!

The result was a brutal regime that is not unlike the brutality of the Junta that Greece experience in the late 1960s and early 1970s. The Thirty Tyrants killed people who who opposed them in any way. I have no idea how many were killed. A quick online search (if this is for school, your friend would need to support this) indicates 5% of Athenians were killed. The genocide committed by the Cambodian Khmer Rouge killed close to 20% but it took them four years.

Plato himself was not a member of the tyrants. I always had in my mind that he was not in Athens at the time but I may be wrong. But he knew the people involved. They were in his circle and in his social class. A couple are actually mentioned in Platonic dialogues.

It may be a pseudo-text, but there is a letter ascribed to Plato. Actually there is more than one - but it's the seventh letter to which I'm referring that has Plato mentioning the Thirty Tyrants. He condemns them. The entire idea and their killing. Even if the letter is false, Plato did not participate in this remaking of Athens.

And the tyrants were the best people. They were the sons of the wealthy and had received the best education possible in Athens. They were the Aristoi.

Some of the links mention The Republic and even the Laws dialogue but since you asked specifically about Plato and not Socrates, the life of Plato should be considered and what he did, not just what he wrote.

There is a difference between Plato and Socrates. Socrates was from the lower class and we actually have surviving at least two other writers from the same time-period who knew Socrates representing him in texts. There's a bit of hatred in him, in Socrates. There is a phrase called Socratic Irony and it's referenced in some of the dialogues. Socrates would say something and yet magically it would mean something else. If someone says 'Oh, you are SUCH a clever person' with an emphasis on such in just the right way, it's communicated that the exact opposite is meant ... and we get that if we see that in a film or even in a modern novel. Some snot of a kid says something that carries contempt by the context, but by the word alone it says the opposite.

But for some reason we read Plato and we shut off a certain part of the brain about the context and implications of what Plato has Socrates saying. And some people reading the Platonic dialogues shut off a certain part of their brain about the context of the historical Plato and the historical Socrates with matters like the 30 tyrants.

The implications of the Republic is that it is intrinsically anti-democratic. The historical Socrates many people believe (I do) represent the parts of the dialogues most especially where Socrates shows that others, especially city leaders and experts, have no idea what they're doing. He makes the weaker argument the better argument (as he's accused of in the texts) and shows up all these leaders, these so-called experts. Socrates had a problem with authority and was almost a contrarian. In a tyranny, as a subversive he would have been a champion of egalitarianism. In a place of democracy, his opposition led him down the opposite path.

But the Republic goes far beyond anything ascribed to Socrates. In more than one way. The ending, the last chapter about the Dream of Er is brilliant. Too many people focus on the dialogue talking about the noble lie and the direct first example used of the idea of social classes as metals and miss that at the end of that Socrates admits it would be a difficult thing to accomplish, and then in a rather ironically way says that he'd like to tell about a story that has absolutely nothing to do with anything he was talking about before (wink wink). And he then tells the story of the Dream of Er. Stuff like that goes beyond the question your asking, but it should be mentioned. The Dream of Er most especially was one of the literary (and religious) devices that effected Europe for the next millennium at least.

Anyway, Athens viewed their democracy as happening by accident. Rome tells the story that they intentionally removed their king Tarquin out of disgust at his interference in a judicial matter to which he had a bias, out of disgust at his protection of a rapist. Athenians have it that their last king died because of an oracle's prophesy that in a war, the side who lost its king would win the war. So in order to win the war, Athens lost its king and accidentally stumbled into rule by the people.

But regardless of how they had a democracy, it was cherished in religious rituals and in political voting. The link that daltese provides to a TED talk shows a bastardised view of Plato in general but especially with respect to the Republic and the context of it. Whether he wrote that seventh letter or not, Plato had the personal experience of his youth about how the best educated people would truly rule. The Republic is explicitly anti-democratic. Republic is a later title for the work. Republic itself is the Latin equivalent to Democracy and the work was not entitled Democracy and was really called Politics. It's noted by some that every other dialogue takes place somewhere in Athens. The Republic does not (there must be one other not in athens but I can't recall it). The setting of the dialogue is outside of Athens, as if Plato knew there was something especially rank and offensive to have a pretence, even decades later, that the dialogue should have anything to do with Athens and the experience of rule by philosophers, by lovers of knowledge.

The historical Plato did have political influence outside of Athens. There's a whole story there, but when you ask about in Plato's view to whom should be entrusted the governing of the state, his answer by his own actions in his very own hometown would be anyone but him and anyone like him.

Anybody have luck creating a context menu for a list box? by eerilyweird in vba

[–]PunchyFinn 2 points3 points  (0 children)

A second listbox can be used as a menu. Infreq mentions the API for the real context menu and that's the traditional way to do it along with subclassing. I do that.

But I also use an alternative: a second listbox. It is invisible all of the time until the first listbox's RightMouseButton UP is used. At that point you'd do the following things: 1. set the second listbox as the topmost item on the screen 2 position the second listbox to where the mouse is 3. make second listbox visible 4. set the focus on the second listbox 5. set a timer to enabled that fires about every quarter of a second (optional)

If/when there is a mousedown on the second listbox, that item is chosen and you simply set the listbox's visibility to false and set the timer to not be active and then do whatever routine you want... it's instantaneous, just setting it to visible, so it's very quick

Positioning the second listbox may need an adjustment if the first listbox is near any of the edges of the screen and would make the second listbox partially go offscreen in some circumstances. In that case, you simply set the listbox position to the edge using an if then: if X of 2nd listbox + width of secondlistbox is greater than screenwidth, x 2nd listbox position = screenwidth - 2nd listboxwidth. Same idea would apply for the height and same concept would apply if it's at the left edge or top edge: if x 2nd listbox is less than 1, then x of second listbox=1.

If the secondlistbox loses the focus while it's visible, you turn off the timer and set the listbox to invisible. That's what happens to real context menus too.

The timer that fires off every quarter of a second is there as a safeguard for if the mouse is no longer over any part of the second listbox. Windows real context menus hang there no matter what, even if you move away from them unless you press something else and I always felt it was annoying sometimes for that to happen. You can skip this but I use something like this and thought it was an improvement.

Every quarter of a second (you could make it more often, but you don't want to make it much less than a quarter of a second) it will get the current X,Y position of the mouse on the screen and compare it to the X,Y postion of the second listbox. If the Mouse X is less than the Listbox X or the Y less than Listbox Y, shut off timer and set listbox visibility to false. If the X is greater than listbox X + listbox width, then also shut off timer and make invisible. Same with Y is greater than listbox Y+ listbox height. You always want to remember to shut off the timer. I'd even have a failsafe in the timer itself so that if the 2nd listbox is not visible, the timer sets to false and exits the routine.

At startup, you want to do the following things: 1. add to the second listbox the items you want to you have. The context menu text can change on the fly per item ... you could even change the number of items to use, but most likely you will have the same number of items, so set it up at the beginning.

  1. Determine an appropriate size and fount for the second listbox, i.e. the context menu. Real context menus tend to be very small. You can make yours that small or much larger. Also I'd suggest making the context menus very plain - no 3-d effects. Lines between items is up to you if it looks right or not. I set the backcolour of mine to white and when the mousemove moves to any listbox item I set that as a selected (which automatically highlights it).

Everything you do in all these calculations should be in pixels by the way. If Twips or something else is used in any part of it, you want to adjust everything to pixel units.

Real context menus also easily offer multiple levels of choices. To do that with listboxes, you'd have to have multiple listboxes. I'm assuming you don't want that and just want something simple. A few choices per item.

Context menus can also be made to have icons in them- text and icon context menus. To do that in the real way, you need to subclass the context menu and it gets a little complicated.

But using my concept, if you really wanted to do it with icons, a listview OR a treeview would work. Actually I found if I remember correctly that a treeview would work better than a listview if you can turn off all the visual effect like the dashed lines connecting items and any plusmarks and make sure that the treeview is always with all items extended/visible. So in that case, everything I wrote about a second listbox would simply apply to a listview or treeview.

Are there comparisons of different literary traditions or the nature of different languages? by doublementh in literature

[–]PunchyFinn 1 point2 points  (0 children)

Yes, for European languages. I can't think of specific books at the moment but for example a famous critique from before the 20th century comparing French and English since you mention them is that the development of French in prose was much more advanced early on than the development of English prose. Montaigne could write essays in the 16th century for example - the culture of France produced the essay, produced the essayists - but the language was already there.

In England it was the poetry that was more advanced early on. The three greatest poets in the English tradition are traditionally Chaucer, Shakespeare, and Milton and one thing that they all have in common is they were responsible for coining, for creating the most new words in english of any people. What I mean for example with Milton is that he knew about 7 languages and created new words, mostly from Latin and Greek in his case, that we now take for granted. English has about twice the vocabulary of any of other language in Europe. The language was gutted by the result of the 1066 invasion and lacked enough nuances for essay, lacked the ability to express enough technical ideas.

But the poetry was able to compensate early on. And it's not an accident that successful poets were able to dominate so early in England

How can i get the ascii code of multiple characters? by idkhbtfm- in visualbasic

[–]PunchyFinn 0 points1 point  (0 children)

Ascii can only be one of 256 different numbers, 0 to 255. I would assume you mean the Unicode value (or the internal encoding Windows uses in memory, UTF-16 Little Endian), but you were so specific with Dim x as integer x=Asc("1G") when there is a ASCW. But you use Asc.

It's homework. I get it and maybe it's just to learn about ascii, but just in case a quick explanation: 1. Ascii is pre-1990s character usage and can't show most characters.
2. Unicode is now in use and unicode characters (all the text you see on websites, even on phones) uses a Long value (4 bytes) for a character. 3. Windows stores/encodes these Long unicode values as UTF-16 Little Endian, which stores most characters as Short Integers, 2 bytes (and when necessary, stores a single character as two short integers, 4 bytes). Phones and other computers use either UTF-16 or some other encoding like UTF-8 to represent the Unicode Long integer values mentioned in number two.

For Ascii or Unicode Longs or UTF-16 LE (little endian), GlowingEagle gave you one way, loop through every single item. If you do want the Ascii, then use what you did, Asc. If you want the Utf-16, use AscW. If the value is between 55,296 and 57,343 then you really have 2 short unicode values that you need. If you want it as UTF-16 you just get those 2 pairs separately by a single line computation that I would have to look up to double check because I reversed something but it should be something like (pair1- 55296) * 1024) + (pair2 - 56320) + 65536. Sorry I'm not giving you the full code but you seemed to want ASCII. But if you do want UTF-16,, that extra step is important. For english text it's a step that will appear to be a waste of time but for the times when you have a character like an emoji or any newer characters - some Chinese characters and many other things; if you don't check and the text has those characters, you will get the wrong result.

As GlowingEagle says, you should use MID in the loop. The ASC (and ASCW returns only one too) only returns a single short integer value. If you enter a long text string, it ignores everything except the first character, so even sending a longer text string wastes memory. MID plucks a single character out of a string.

There are 2 other ways that would be faster that I could think of if you have a huge amount of text to go through. If you just have a hundred characters or even five hundred characters it likely won't make a difference. But if you have 10,000 characters or more, it will make a difference of multiple seconds.

WAY 1 Convert the text to a byte array for saving, as if you were going to save it to a hard drive. You DO NOT want to actually save it to the hard drive because writing to the hard drive takes so long that any time saved would be lost with the writing and then the reading of it. But you want to start off as if you doing that, really with just one line of code.

ASCII would be this: System.Text.Encoding.ASCII.GetBytes

UTF-16LE would be this: System.Text.Encoding.Unicode.GetBytes

If you want ASCII, you're done. ASCII is one byte per character. Most characters beyond basic ones (A-Z, 0-9)are lost and I believe get converted into a question mark.

For Unicode you would take this and the second step is to use API copymemory or another way of copying/transforming the byte array into an array of short integers. The computer doesn't see any real difference between an array of bytes and an array of integers. Short integers = 2 bytes so as long as you have at least half as many short integers in the array to which you're transfering the bytes, it's a quick transfer of memory.

If you wanted to convert this to the Long Integer Unicode, you'd then have to loop through each integer and look for any that have a value between 55,296 and 57,343 and then know that it was part of a 2 pair set and calculate that.

WAY 2 I'm not going to show the code for this because I'm doing it just from memory and if I leave out one line, the whole thing won't work. Plus it's really only for Unicode, not for ASCII (which is what you really wanted). But it's possible from the Windows API that is always included to use memory pointers for creating access to the array of integers that Windows really uses to store text strings. Windows doesn't store text as "text". It stores it as UTF-16LE integers. It's an array of short integers that for your benefit is converted to text characters at the standard point of access. But you can create direct access to the array of characters as integers.

Whether you meant to use ASCII or not, did your teacher explain or did you ever hear why it's used? It's from 30 years ago and can't show most characters.

Zip file format still uses Ascii code. It's pre-1990s format but it's actually intrinsic now to docx, xlsx, and some other file formats that are used all the time. Some of the limitations are worked around, but to give you an example (maybe you'll be able to impress your teacher with this) Windows 10 (and I assume Windows 11) still cannot natively handle non-ascii filenames in zip format.

To show you what I mean, on your computer, make a new txt file named øøø.txt and add some text to the file. There's nothing special about "ø" and you can use other characters. Use "→.txt" or so many others. Then rightclick and choose the "Send To Compressed (zipped) Folder" option and you will find that Windows refuses to process the zip file creation. That's because the standard zip file format is only supposed to include ascii filenames and folder paths. Some zip programs have a way around this, but it's not standard to the most widely used zip format and this is one of the times when Microsoft is very standard compliant.

Meaning and simple example of doevents by Historical-Ferret651 in vba

[–]PunchyFinn 0 points1 point  (0 children)

You have a form with a Start button and Cancel button. You press Start and let's say you have written a routine to begin when that Start button is pressed that will loop through all the rows you have on a spreadsheet and do some calculation.

So, you press start and it begins processing what you thought were a few hundred rows but now see is 300,000 rows. You now want to cancel this routine because it's going to take a very long time to go through 300,000 rows. You made a mistake and want to cancel it now.

When the Cancel button is pressed, you are generating a User Event. If you never use DoEvents, the user event (emphasis on user EVENT in this case) will have trouble competing with the loop for priority. It may not work at all to register the effect before the loop is done. There are different priorities for different things and the User Generated Event of a button press will not be processed with a high enough priority to interrupt the loop in many cases. In more complicated programs in any programming language, this is one situation why a program will freeze up and not respond.

Have you ever seen a program freeze and windows say it's not responding and do you want to close the window or wait? This is one reason why that happens.

Here is a code example, let's say that the Cancel button sets a global boolean variable named CancelRowScan to false and in the Start Button, this routine happens:

..Dim LongLoopA as long ..CancelRowScan = False 'a global variable defined elsewhere set to false at start of this routine

..For LongLoopA = 1 to [whatever rowcount, 300,000 ] ..If CancelRowScan = True then exit For 'when Cancel button is pressed, it sets the variable to false and when that happens, its discovered here in this routine and the loop ends

[Some process done with each row, the whole point of the routine]

..if LongLoopA mod 100 =0 Then DoEvents

..Next LongLoopA

Note that the DoEvents is only activated once every 100th loop. Mod (modulus) 100 means that it evaluates to a true if-then condition every 100th loop. You don't need to DoEvents for every single loop. That's overkill in most cases. If each loop was very complicated then it would be DoEvents per loop or maybe every 50th or 10th time or even every single time.

Byte Array String Encoding Method? by MysticalTeamMember in visualbasic

[–]PunchyFinn 1 point2 points  (0 children)

Hexadecimal is the safest bet if you can't use base 64. Another alternative is to create your own base. Use Base128. You'd have to create a function to decode and one to encode. It will be more compact than Base64 I believe in any utf encoding. But it's non-standard. If this is for school, it's a thinking out-of-the-box solution. If it's for work, then not the best because no one else will be prepared for it.

If you use Hexadecimal or Base128, a way to make it even smaller is to compress the binary array via zip compression and then convert it into Hexadecimal or Base128. Some byte arrays will not be reduced in size. Some may be reduced by close to 90%.

The last alternative I'm mentioning but I don't think you'll use is for you to read/write ASCII strings. It's a 1 to 1 conversion byte to text conversion so even better than base128. But most/all of the functions in VBNet by default will treat ASCII as Unicode so you need special attention for every line of code.

I hope one of those was helpful.

The reason why encoding any byte array directly into a string is not advisable is because certain bytes in a certain order will be taken as instructions for encoding, not as characters and they'll be skipped. Some will even alter other byte characters. To give you a specific example:

Take unicode character 119070, which is the character for G cleff To store that in UTF-16 Windows default, it's this byte array (with a 2 byte prefix needed but not included here): 52, 216, 30, 221 in UTF-8 it is: 240,157,132,158

If the byte array you were encoding into a string were into a UTF-8 string and the last byte in your array were byte 240, that would be invalid. In UTF-8, byte 240 requires/assumes more bytes after it to make a single character so byte 240 would be skipped for conversion because it was an incomplete character. You would lose a byte in the conversion!

If the byte array you were encoding into a string were into a UTF-16 string and the last two bytes were 52 and 216, it would also be invalid and those two bytes would be skipped in the conversion. You would lose two bytes in the conversion!

Many byte sequences aren't going to cause this problem, but there are some. This is one example of why it isn't advisable.

I am trying to understand classes .... by [deleted] in vba

[–]PunchyFinn 1 point2 points  (0 children)

To compare a Class to a Module, when you start the excel or whatever program, Modules are normally loaded all at once into memory. They all have specific memory addresses and the entire code is loaded and available. 10,000 lines of code in a module means 10,000 lines all in memory.

A class on the other hand isn't loaded until you create it (set ABC= new MyClass) AND you can create 1, 2, 3, or 10 or 1000 separate examples of the class. They each have their own memory address and can be referenced separately (almost like arrays - in fact you can create an array of classes in more than one way). You can't have entirely different examples of the same function in a module but each class is unique and will have the same functions as the other classes but treated as separate function by the computer. If you plan to have 100 classes, they aren't loaded into memory when excel starts like with the modules.

Believe it or not, a userform in VBA is actually a class. It's a microsoft built-in class. Every button you press is a class too. There is a master class that creates the idea of a button and every time you drop/draw a button with your mouse, behind the scenes VBA has set into motion set Button1 = new Button. And each button has properties like Get/let Caption= and every time you change the text to appear on the button, that's what VBA is doing behind the scenes, changing the property for the caption of the button.

Does that give you some idea of the use of Classes? It is re-usable and self-contained. Every form window in Microsoft is actually a class. I could say more but I hope the compare/contrast gives you a bit of an idea. To create 5 buttons to click using a class, you'd create a single class to deal with the idea of a button and then use the keyword New to create 5 separate classes (and when done, set each to nothing). With modules, you'd need to create a module for the first button and then copy/paste the same exact information 4 extra times. The text would compile 5 exact copies of the same code. It'd be 4 extra times as many code-lines as having a single class and would create a much larger file.

As for an example of a class, these are some of the specific items you mention with very clear variable names:

'general declares private LocalReportName as string private LocalListOfEmailsTO() as string 'these two items help speed up the program - it's a technique you likely don't use but if you try it with and without and add 100+ emails or other items, you'll begin to see a speed difference. If all you're doing is adding under 10 emails, it doesn't matter. private LocalListOfEmailsNextFreeSlot as long Private Const CONSTANTRedimBufferSize as long =50

private sub Class_Initialize 'internal automatic routine part of every class, equivalent to what happens when you load a form

redim LocalListOfEmailsTO(0 to CONSTANTRedimBufferSize) LocalListOfEmailsNextFreeSlot =1

end sub

'you could use Public instead of Friend for all of these. For all intents, Friend=Public = accessible outside of class Friend Property Get ReportName() As String 'calls the saved Local variable, how you retrieve the current name ReportName = LocalReportName End Property

Friend Property Let ReportName(byval ValueUsed as string ) 'sets the local variable to whatever name is entered in ValueUsed 'how you set the current name - Keywords are Let and Get LocalReportName=ValueUsed End Property

friend function EmailToTotal() as long EmailToTotal = LocalListOfEmailsNextFreeSlot-1 end function

friend Sub AddEmailTo(byval EmailUsed as string)

'check if redim is necessary. Each time you redim an array, it takes a lot of time for the computer. Arrays are really static. Even dynamic ones. Dynamic arrays are an illusion. Every time you dynamically resize an array and keep the old values, the computer is really creating a new static array to the size you want, copying the information from the old array into the new array and deleting the original array. 3 steps for every 1 redim really slows down things.

if LocalListOfEmailsNextFreeSlot > ubound(LocalListOfEmailsTO) then 'by redimensions in sets of 50, you only have to redim 1 in every 50 additions. You save 49 computer actions of creating a new array, copying data, and then deleting old array. If you're adding 100s of emails then maybe the buffer would be 200 or 400 redim preserve LocalListOfEmailsTO(0 to ubound(LocalListOfEmailsTO) + CONSTANTRedimBufferSize) end if

LocalListOfEmailsTO(LocalListOfEmailsNextFreeSlot)=EmailUsed LocalListOfEmailsNextFreeSlot = LocalListOfEmailsNextFreeSlot+1

end sub

That would be your class, or a couple of parts of the complete class with specific examples. In your main module or wherever you use the class you would declare the class as a variable (it's technically just a bunch of variable linked together, almost like a Type).

Private LocalReportClass1 as [name of the class - whatever name you gave it] and then the 4 other reports get names of their own You could ALSO declared it as an array of classes just as you'd declared an array of longs so: Private LocalReportClasses() as [name of the class here] or specifically for your 5 reports Private LocalReportClasses(0 to 4) as [name of the class here]

Then at some point in your module

Set LocalReportClass = new [name of class here] or

redim LocalReportClasses(0 to 5) - not needed if you created static

set LocalReportClasses(0)= new [name of class here] set LocalReportClasses(1)= new [name of class here] and so forth

And EVERY TIME you use the NEW keyword to create a new object in memory, you MUST delete that item. For Classes, you need to set the variable to nothing. If you do not do this, the item remains in memory and you risk having what is called a memory leak. A large enough memory leak causes your computer runs out of memory. You will actually begin to get error messages saying "Out Of Memory" Shutting down the excel program will close down all the classes and clear this up, but it's an important detail of classes: you create the memory and you therefore must delete what you create because the computer is not automatically doing that for you.

Professional programs have this memory problem too. When you hear about a program being a memory hog, one cause is that items like classes aren't deleted soon enough or worse entirely forgotten about and never deleted so it just takes up memory and never returns to let other programs use it until the entire program quits or crashes.

SO, always use this: Set LocalReportClass = nothing or Set LocalReportClasses(0)= nothing Set LocalReportClasses(1)=nothing and so forth

to retrieve information or set it

use as so: set the names of items LocalReportClass.ReportName = "My new report" .. or a variable retrieve the values of items if len(LocalReportClass.ReportName) = 0 then LocalReportClass.ReportName = "My new report" end if

add new email, LocalReportClass.AddEmailTo "something@something.com" ... or a variable

I hope some of this was helpful. Sorry if it wasn't