PDA

View Full Version : Solved: Lorem Ipsum generator



TrippyTom
05-31-2007, 11:13 AM
Hi everyone,

For an exercise in learning, I thought about making a Lorem Ipsum generator like the one here: http://www.lipsum.com/

I just want to use the first 10 paragraphs though from the Lorem Ipsum text and work with that. I presume this would involve arrays, but I'm very inexperienced with arrays. Does anyone have a good suggestion on how I should approach it?

Oorang
06-01-2007, 06:14 AM
Put the whole text as a string constant. For letters use mid. For words, load the string into a byte array and loop through it counting spaces to get the position of the correct break, then use mid again. For sentences do the same but count periods. For paragraphs count line breaks. (Make sue you put line breaks into the constant.) For lists prepend the constant with bullet then replace all occurances of period with period / bullet / line break, then remove the final period / bullet / line with just period.

TrippyTom
06-01-2007, 10:02 AM
Can I have that much text as a constant? Is there no maximum character limit (like 255) or something?

Oorang
06-01-2007, 10:38 AM
Short answer.... Yes.
The only limit to a constant is the limitations of the constant datatype. A VB string has no limit but the machine it is on. The minimum memory for Win XP is 256 MB. The average PC now has at least 1GB of RAM. However assume you wanted to by polite and keep it under 10KB. 10KB is 10,485,760 bytes. A VB string 6 byte plus 4 bytes for every character. So subtract 6 and divide by 4 and you end up with 2,621,438 characters. The KJV New Testament has 179,011 words. The average word in the english language is 7 characters. Add 1 for spaces and you and up with 1,432,088 characters. There are 7957 verses, so assume an average of 5 punctuation characters per verse so that adds 39785 characters for a total of 1,471,873, and you are still haven't hit the limit.
So uh yes, I think Lorem Ipsum will be alright ;)

TrippyTom
06-01-2007, 10:54 AM
Hmm, I must be doing something wrong then. I used & vbcr after every paragraph and my messagebox is showing me it's stopping at a point (see image).

Oorang
06-01-2007, 12:08 PM
Ah well THAT is a limitation of the MsgBox function. It displays up to 1023 characters. You can set a reference to the windows scripting host and use the popup method for larger text.

The Article Below uses late binding.
http://www.microsoft.com/technet/scriptcenter/resources/qanda/jun05/hey0602.mspx

Here is how to do it with early binding:
Set reference to Windows Script Host Object Model (wshom.ocx), then:

Sub Popup()
Dim Shll As WshShell
Dim Msg As String
Msg = VBA.String$(1023, ".") & "X"
MsgBox Msg
Set Shll = New WshShell
Shll.Popup Msg
Msg = Msg & Msg & Msg & Msg
Shll.Popup Msg
End Sub

TrippyTom
06-01-2007, 02:09 PM
Ok, well I was just using the MsgBox for testing. Ideally, I would like to direct the result into a text box on my userform so the user can copy/paste it. Will this have the same limitations?

Oorang
06-03-2007, 12:21 PM
Which textbox control are you using?

TrippyTom
06-04-2007, 05:22 PM
I'm not sure what you mean :)
It's just a normal TextBox control from the userform toolbar.
I set WordWrap to TRUE and Scrollbars to VERTICAL.

Oorang
06-04-2007, 07:22 PM
I have not hit a limit on the text box yet. But to give you a more defined answer I would need to test it's performance out. Some controls really bog on a lot of date (like the list view). Might be fun to see how your program does with textbox.value vs a label.caption.

I suppose worstcase you could use and embedded worddoc. But I suspect you will be fine with a textbox:D

TrippyTom
06-05-2007, 08:32 AM
Here's what my userform looks like. My code is in the very beginning stages - I just have to figure out the parsing now (the hardest part of course). hehe

Oorang
06-05-2007, 11:09 AM
hehe.. I love it :D

TrippyTom
06-05-2007, 04:44 PM
Ok, I figured out how to do letters. Now I was wondering if you could explain a byte array so I can tackle Words. Once I figure that out, I'm sure the transition to Sentences and Paragraphs will be easy.

Oorang
06-05-2007, 05:47 PM
Byte arrays are fairly simple. It is just what it sounds like, an array of numbers which are typed a "Byte" (compare to Long Array, String Array, etc) If you do this:


Dim MyByteArray() As Byte
Const MyTestString_c As String = "Test"
MyByteArray = VBA.StrConv(MyTestString_c, vbFromUnicode)

Your string will be put into the byte array. Now how to read it? Each element will be the ASCII Value of it's corresponding Character. Therefor MyByteArray(0) = 84 which is the ASCII value for "T", MyByteArray(1) = 101 etc. (see http://www.asciitable.com/ for the codes). So you can quickly count spaces like so:


Function CountSpaces(Value As String) As Long
Dim MyByteArray() As Byte
Dim Char As Long
Dim Counter As Long
Const LowerBound As Long = 0
Const Increment As Long = 1
MyByteArray = VBA.StrConv(Value, vbFromUnicode)
For Char = LowerBound To UBound(MyByteArray)
If MyByteArray(Char) = vbKeySpace Then Counter = Counter + Increment
Next Char
CountSpaces = Counter
End Function

There are many other ways to do this as well, but as you get into heavy duty string manipulation, VBA gets a little slow, and byte arrays are quite fast.


*Note: If you want to get really fancy, I believe you can replace


If MyByteArray(Char) = vbKeySpace Then Counter = Counter + Increment

with


Counter = Counter - (MyByteArray(Char) = vbKeySpace)


For a performance gain.

TrippyTom
06-06-2007, 10:07 AM
Wow Oorang, I think this is going to take me a while to digest, but I don't see where you're calling the function. I presume I would put that somewhere after the MyByteArray = VBA.StrConv(MyTestString_c, vbFromUnicode) line?

Here's my code so far:


Private Sub btnGenerate_Click()
On Error Resume Next
Dim Shll As WshShell
Dim Msg As String
Msg = "Lorem ipsum dolor sit amet, ..."
'Set Shll = New WshShell
'Shll.Popup Msg
'Letters
'tbResult.Value = Mid(Msg, 1, tbNumber)
If optParas = True Then
'Paragraphs
'call Function for Paragraphs
ElseIf optSentences = True Then
'Sentences
'call Function for Sentences
ElseIf optWords = True Then
'Words
Dim MyByteArray() As Byte
'Const MyTestString_c As String = "Test"
MyByteArray = VBA.StrConv(Msg, vbFromUnicode)
tbResult.Value = Mid(Msg, 1, CountSpaces(tbNumber.Value))
ElseIf optLists = True Then
'Lists
'call Function for Sentences
End If
Msg = Empty
End Sub

TrippyTom
06-06-2007, 11:15 AM
Ok, I think I figured out how to adapt your code to mine:


ElseIf optWords = True Then
'Words (count spaces)
Dim CountSpaces As Long
Dim MyByteArray() As Byte
MyByteArray = VBA.StrConv(Msg, vbFromUnicode)
Dim Char As Long
Dim Counter As Long
Const LowerBound As Long = 0
Const Increment As Long = 1
For Char = LowerBound To UBound(MyByteArray)
If MyByteArray(Char) = vbKeySpace Then Counter = Counter + Increment
CountSpaces = Counter
If CountSpaces = tbNumber Then Exit For
Next Char
tbResult.Value = Mid(Msg, 1, Char)


Thanks so much Oorang!!! :thumb

TrippyTom
06-06-2007, 11:26 AM
I don't think I'm adding the new lines into my constant properly.
I'm using:


msg = "...sollicitudin. " & vbCr
Msg = Msg & "Suspendisse ..."


But it's not finding the return. How would I insert a carriage return into my constant correctly? Looking at the ASCII table you posted a link to, it looks like it might be code 13... but I'm not sure.

[edit] -- I figured this part out. :)