Removing Brackets and Text in Crystal - crystal-reports

I am using this following text to delete brackets and text inside the brackets; I need to go threw the entire memo field and it stops after it finds and deletes the first set of brackets and text.
if right({table.col},1) = "]" then
left({table.col},instr({table.col},"[")-1)
else
{table.col}
Any suggestions...

This tested well with Crystal2008, not sure what version you are using, it also would need some error checking to handle mismatched bracket pairs, but it may offer some food for thought:
Dim workString as String
Dim bracketedText as string
if (InStr({table.col},"[") > 0) then
workString = {table.col}
while(InStr(workString,"[") > 0 )
bracketedText = "[" + ExtractString(workString,"[","]") + "]"
workString = replace(workString,bracketedText,"")
Wend
Formula = workString
else
Formula = {table.col}
End If

Related

Is there a way to count the number of actual replaces when using replaceAll in OO Basic?

Considering the example for search & replace of specific uk-to-us words from the Editing Text Documents OO Wiki:
Dim I As Long
Dim Doc As Object
Dim Replace As Object
Dim BritishWords(5) As String
Dim USWords(5) As String
BritishWords() = Array("colour", "neighbour", "centre", "behaviour", _
"metre", "through")
USWords() = Array("color", "neighbor", "center", "behavior", _
"meter", "thru")
Doc = ThisComponent
Replace = Doc.createReplaceDescriptor
For I = 0 To 5
Replace.SearchString = BritishWords(I)
Replace.ReplaceString = USWords(I)
Doc.replaceAll(Replace)
Next I
Question: is there a way to get the count of actual replacement that has been made ? (if any) I don't mind the individual count for each term, but just globally – i.e. if, say, the original text included 2 occurences for 'colour' and 1 for 'behaviour', in the end to get the number 3 (purpose: to report this number to user as info via MsgBox).
As shown in the example at https://www.openoffice.org/api/docs/common/ref/com/sun/star/util/XReplaceable.html, the number found is returned.
Dim TotalFound As Long
TotalFound = 0
...
TotalFound = TotalFound + Doc.replaceAll(Replace)
Next I
MsgBox "Replaced " & TotalFound & " occurrences"
Result: Replaced 3 occurrences

insert and delete text after an Range-position in Word

I have a SET-field in Word 2007. After the set-field there could be everything (text,bookmark, SET field,...). I want to add a text (e.g. "exampletext") in between.
After this I want to delete this inserted text (but I don't want to search through the whole document).
Is there a method?
Trial 1 (it inserts it in the field - and not after the field):
' xStartReturn is a field
Dim myExampletext As WordApp.Range = objDoc.Range(xStartReturn.Code.End, xStartReturn.Code.End )
myExampletext.Text = "exampletext"
Trial 2 (leads to the problem that I don't get the Range-field to delete the exampletext afterwards):
xEndeReturn.insertAfter("exampletext")
Trial 3:
'xStartReturn.Code.End + 1 doesn't work.. but I found out that the "}"-Sign in the setField is +20 after xStartReturn.Code.End. Theoretical this should work - but there could be e.g. also paragraph afterwards.
'-> I can automatically check that there is a paragraph - but why is the exampletext added **after** the paragraph?
Dim example As WordApp.Range = objDoc.Range(xStartReturn.Code.End + 20, xStartReturn.Code.End + 20)
example.Text = "exampletext"
Dim later As WordApp.Range = objBasisvorlage_.Range(objXStartReturn.Code.End + 20, objXStartReturn.Code.End + 20 + "SDFSD".Length) 'this is wrong?!
later.Delete()
The following works for me. Since you didn't give us a minimum code with which to reproduce the problem I don't know how relevant the framework is that I used. But you should be able to follow the steps.
Watch what I do with r_f_Code (field code range). You can ignore/remove r_f_Result as I had that in for reference and debugging purposes.
Collapsing the field code range to its end-point leaves the range just within the field braces. Moving the starting point one character to the right puts it just outside the braces, but before anything else. (Note: I tested with two immediately adjacent SET fields.)
My code then enters some text and bookmarks it. That's the only way you do what you ask if what follows the SET field can be "anything". Although I suppose you could insert a Content Control - that would be uniquely identifiable if you go about it correctly...
Sub PositionAfterFieldCode()
Dim f As word.Field
Dim r_f_Code As word.Range, r_f_Result As word.Range
For Each f In ActiveDocument.Fields
If f.Type = wdFieldSet Then
Set r_f_Code = f.code
Set r_f_Result = f.result
'Debug.Print Len(r_f_Code), r_f_Code.Text, Len(r_f_Result), r_f_Result.Text
r_f_Code.Collapse wdCollapseEnd
r_f_Code.MoveStart wdCharacter, 1
'r_f_Code.Select
r_f_Code.Text = "abc"
r_f_Code.Bookmarks.Add "AfterSet", r_f_Code
Exit For
End If
Next
End Sub

Finding text AND fields with variable content in Word

I need to find and delete every occurrence of the following pattern in a Word 2010 document:
RPDIS→ text {INCLUDEPICTURE c:\xxx\xxx.png" \*MERGEFORMAT} text ←RPDIS
Where:
RPDIS→ and ←RPDIS are start and end delimiters
Between the start and end delimiters there can be just text or text and fields with variable content
The * wildcard in the Word Find and Replace dialog box will find the pattern if it contains text only but it will ignore patterns where text is combined with fields. And ^19 will find the field but not the rest of the pattern until the end delimiter.
Can anyone help, please?
Here's a VBA solution. It wildcard searches for RPDIS→*←RPDIS. If the found text contains ^19 (assuming field codes visible; if objects are visible instead of field codes, then the appropriate test is text contains ^01), the found text is deleted. Note that this DOES NOT care about the type of embedded field --- it will delete ANY AND ALL embedded fields that occur between RPDIS→ and ←RPDIS, so use at your own risk. Also, the code has ChrW(8594) and ChrW(8592) to match right-arrow and left-arrow respectively. You may need to change that if your arrows are encoded differently.
Sub test()
Dim wdDoc As Word.Document
Dim r As Word.Range
Dim s As String
' Const c As Integer = 19 ' Works when field codes are visible
Const c As Integer = 1 ' Works when objects are visible
Set wdDoc = ActiveDocument
Set r = wdDoc.Content
With r.Find
.Text = "RPDIS" & ChrW(8594) & "*" & ChrW(8592) & "RPDIS"
.MatchWildcards = True
While .Execute
s = r.Text
If InStr(1, s, chr(c), vbTextCompare) > 0 Then
Debug.Print "Delete: " & s
' r.Delete ' This line commented out for testing; remove comments to actively delete
Else
Debug.Print "Keep: " & s
End If
Wend
End With
End Sub
Hope that helps.

How to count the visible number of lines of text in a text box on an MS Access form

OK, here's what I am trying to achieve. I have an MS Access 2016 DB with a form on it - one of the fields is a text field (max 255 chars), that users can enter "notes", by date.
The form is a continuous form, and there are a LOT of notes. And as most notes are only a single sentence, not the full 255 chars, to save screen space, the text box is sized to only allow show two lines of text (users can double click on the note to see the full text in the rare instances that the text is up to 255 chars).
The problem with this approach is that it is not always clear if a note goes beyond the two lines.
So I am trying to find a way to tell how many lines of text the note uses in the text box, and then I'll highlight the text box if this is the case.
Note what I am talking about here is text wrapping within a text box, not (necessarily) text with line breaks (although there may be line breaks also). Given the wrapping changes dependent upon the text (eg long words will "wrap early" to a new line), so using a simple char count doesn't work, even with a monospace font.
I have searched a lot online and found nothing, except a ref to a possible solution here:
http://www.lebans.com/textwidth-height.htm
But the download is an old Access file type I can no longer open.
Does anyone have any ideas (except for a form redesign - which is my last option hopefully!)
To count the number of lines in a string, or text box, you can use this expression:
UBound(Split(str, vbCrLf))
So
UBound(Split([textBoxName], vbCrLf))
OK, I have come up with a "solution" to this - it's neither neat nor fast, but it appears to work in my situation. I have posted the VBA code for anyone for whom it might interest.
This function is then used on a continuous form's textbox conditional highlighting, so I can highlight those instances where the text has wrapped beyond "n" lines (in my case, two lines)
FYI it's only partially tested, with no error handling!
' Returns TRUE if the text in a textbox wraps/breaks beyond the number of visible lines in the text box (before scrolling)
' THIS ONLY WORKS FOR MONOSPACE FONTS IN A TEXTBOX WHERE WE KNOW THE WidthInMonospaceCharacters
' WidthInMonospaceCharacters = number of MONOSPACE characters to EXACTLY fill one line in your text box (needs to be counted manually
' VisibleLinesInTextBox = number of lines your text box shows on screen (without scrolling)
Function UnseenLinesInTextBox(YourText As String, WidthInMonospaceCharacters As Long, VisibleLinesInTextBox As Long) As Boolean
Dim LineBreakTexts() As String
Dim CleanText As String
Dim LineCount As Long
Dim LineBreaks As Long
Dim i As Long
' Doesn't matter if we can't see invisible end spaces/line breaks, so lose them
' NB advise cleaning text whenver data updated then no need to run this line
CleanText = ClearEndSpacesAndLineBreaks(YourText)
' Check for any line breaks
LineBreakTexts = Split(CleanText, vbCrLf)
' Too many line breaks means we can't be all in the textbox, so report and GTFOOD
LineBreaks = UBound(LineBreakTexts)
If LineBreaks >= VisibleLinesInTextBox Then
UnseenLinesInTextBox = True
GoTo CleanExit
End If
' No line breaks, and text too short to wrap, so exit
If LineBreaks = 0 And Len(CleanText) <= WidthInMonospaceCharacters Then GoTo CleanExit
' Loop thorough the line break text, and check word wrapping for each
For i = 0 To LineBreaks
LineCount = LineCount + CountWrappedLines(LineBreakTexts(i), WidthInMonospaceCharacters, VisibleLinesInTextBox)
If LineCount > VisibleLinesInTextBox Then
UnseenLinesInTextBox = True
GoTo CleanExit
End If
Next i
CleanExit:
Erase LineBreakTexts
End Function
' Add BugOutLineCount if we are using this simply to see if we are exceeding X number of lines in a textbox
' Put this number of lines here (eg if we have a two line text box, enter 2)
Function CountWrappedLines(YourText As String, WidthInMonospaceCharacters As Long, Optional BugOutLineCount As Long) As Long
Dim SpaceBreakTexts() As String
Dim LineCount As Long, RollingCount As Long, SpaceBreaks As Long, i As Long
Dim WidthAdjust As Long
Dim CheckBugOut As Boolean
Dim tmpLng1 As Long, tmpLng2 As Long
If BugOutLineCount > 0 Then CheckBugOut = True
' Check for space breaks
SpaceBreakTexts = Split(YourText, " ")
SpaceBreaks = UBound(SpaceBreakTexts)
If SpaceBreaks = 0 Then
' No spaces, so text will wrap simply based on the number of characters per line
CountWrappedLines = NoSpacesWrap(YourText, WidthInMonospaceCharacters)
GoTo CleanExit
End If
' Need to count the wrapped line breaks manually
' We must start with at least one line!
LineCount = 1
For i = 0 To SpaceBreaks
tmpLng1 = Len(SpaceBreakTexts(i))
If i = 0 Then
' Do not count spaces in the first word...
RollingCount = RollingCount + tmpLng1
Else
' ... but add spaces to the count for the next texts
RollingCount = 1 + RollingCount + tmpLng1
End If
' Need this adjustment as wrapping works slightly differently between mid and
' end of text
If i = SpaceBreaks Then
WidthAdjust = WidthInMonospaceCharacters
Else
WidthAdjust = WidthInMonospaceCharacters - 1
End If
' Check when we get a wrapped line
If RollingCount > WidthAdjust Then
' Check the the length of the word itself doesn't warp over more than one line
If tmpLng1 > WidthInMonospaceCharacters Then
tmpLng2 = NoSpacesWrap(SpaceBreakTexts(i), WidthInMonospaceCharacters)
If i <> 0 Then
LineCount = LineCount + tmpLng2
Else
LineCount = tmpLng2
End If
' As we have wrapped, then we already have a word on the next line to count in the rolling count
RollingCount = tmpLng1 - ((tmpLng2 - 1) * WidthInMonospaceCharacters)
Else
' New line reached
LineCount = LineCount + 1
' As we have wrapped, then we already have a word on the next line to count in the rolling count
RollingCount = Len(SpaceBreakTexts(i))
End If
End If
If CheckBugOut Then If LineCount > BugOutLineCount Then Exit For
Next i
CountWrappedLines = LineCount
CleanExit:
Erase SpaceBreakTexts
End Function
' Work out how many lines text will wrap if it has NO spaces
Function NoSpacesWrap(YourText As String, WidthInMonospaceCharacters) As Long
Dim WordLines As Double
Dim MyInt As Integer
WordLines = (Len(YourText) / WidthInMonospaceCharacters)
MyInt = Int(WordLines)
' Line(s) are exact width we are looking at
If WordLines - MyInt = 0 Then
NoSpacesWrap = MyInt
Else
NoSpacesWrap = MyInt + 1
End If
End Function
Function ClearEndSpacesAndLineBreaks(YourText As String) As String
Dim str As String
Dim CurrentLength As Long
str = YourText
' Need to loop this in case we have a string of line breaks and spaces invisibly at end of text
Do
CurrentLength = Len(str)
' Clear end spaces
str = RTrim(str)
' Clear end line break(s) whihc are TWO characters long
Do
If Right(str, 2) <> vbCrLf Then Exit Do
str = Left(str, Len(str) - 2)
Loop
If Len(str) = CurrentLength Then Exit Do
Loop
ClearEndSpacesAndLineBreaks = str
End Function
Do please provide any feedback and comments!

RowFilter including [ character in search string

I fill a DataSet and allow the user to enter a search string. Instead of hitting the database again, I set the RowFilter to display the selected data. When the user enters a square bracket ( "[" ) I get an error "Error in Like Operator". I know there is a list of characters that need prefixed with "\" when they are used in a field name, but how do I prevent RowFilter from interpreting "[" as the beginning of a column name?
Note: I am using a dataset from SQL Server.
So, you are trying to filter using the LIKE clause, where you want the "[" or "]" characters to be interpreted as text to be searched ?
From Visual Studio help on the DataColumn.Expression Property :
"If a bracket is in the clause, the bracket characters should be escaped in brackets (for example [[] or []])."
So, you could use code like this :
DataTable dt = new DataTable("t1");
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Description", typeof(string));
dt.Rows.Add(new object[] { 1, "pie"});
dt.Rows.Add(new object[] { 2, "cake [mud]" });
string part = "[mud]";
part = part.Replace("[", "\x01");
part = part.Replace("]", "[]]");
part = part.Replace("\x01", "[[]");
string filter = "Description LIKE '*" + part + "*'";
DataView dv = new DataView(dt, filter, null, DataViewRowState.CurrentRows);
MessageBox.Show("Num Rows selected : " + dv.Count.ToString());
Note that a HACK is used. The character \x01 (which I'm assuming won't be in the "part" variable initially), is used to temporarily replace left brackets. After the right brackets are escaped, the temporary "\x01" characters are replaced with the required escape sequence for the left bracket.