The Mid-function is less then optimal. Problems are - a negative length is treated like no length given - a start position of 0 results in error 5 - a negative start positions returns !br0ken!! Taking inspiration from the way ruby handles strings, I propose improvements as follows. - Mid should take negative length which runs from left to right - it should take negative start positions which are counted to the left, from the last position in the String i.e. the last Position is -1, the next to last is 2 etc.. 0 is the first position before the start of the string, as is -Len(ofthestring) - 1 For details please refer to the definition of the Middle-function below which is largely backwards compatible to Mid, unless you count the throwing of errors and "!br0ken!!" as intended behaviour. It might break programs which rely on a negative length being treated as no length. Sub MiddleDemo Dim sText As String sText = "abcdefghijkl" Print "The Mid-function is " & Mid(sText, -1) Print Middle(sText, 0, 3) 'the first two characters Print Middle(sText, -1, -4) 'the last four characters Call Middle(sText, 6, -3, "456") 'replace three characters counted to the left from the sixth position Print sText End Sub Function Middle(sText As String, Optional lStart As Long, Optional lLen As Long, Optional sInsert As String) As String If IsMissing(lStart) Then lStart = 1 Dim lLenText As Long lLenText = Len(sText) If IsMissing(lLen) Then If lStart >= 0 Then lLen = lLenText 'get whole text up to the end of the string Else lLen = -lLenText 'get whole text up to the start of the string End If End If Dim lMidStart As Long 'start of the string to return, we intend to use the orginal Mid-function If lStart < 0 Then lMidStart = lLenText + 1 + lStart 'convert negative position to corresponding positive position Else lMidStart = lStart End If Dim lMidLen As Long 'length of the string to return If lLen < 0 Then 'the string to return is on the left to lMidStart lMidStart = lMidStart + 1 + lLen 'start of the string lMidLen = -lLen Else 'the string to return is right to lMidStart lMidLen = lLen End If If lMidStart < 1 Then 'start still negative, lMidLen = lMidLen + lMidStart - 1 'length must be shortened, so that we cab use thr original Mid-function lMidStart = 1 'the string to return starts from the first position End If 'if lMidLen isn't positiv, return an empty string If lMidLen < 1 Then 'we can't give a negative length to the original Mid, because ist would return the whole string sText Middle = "" Else 'ready to use the original Mid Middle = Mid(sText, lMidStart, lMidLen) End If If IsMissing(sInsert) Then Exit Function 'don't change the string sText, so we are done sText = Left(sText, lMidStart - 1) & sInsert & Mid(sText, lMidStart + lMidLen) End Function
Oops! Sorry the Middle-function was buggy. Here's correction. Function Middle(sText As String, Optional lStart As Long, Optional lLen As Long, Optional sInsert As String) As String 'like Mid, but takes negative lLen which runs from left to right 'also negative lStart which are counted to the left, from the 'last position in the String i.e. the last Position ist -1 'On Error GoTo Err_Middle If IsMissing(lStart) Then lStart = 1 Dim lLenText As Long lLenText = Len(sText) If IsMissing(lLen) Then Select Case lStart Case > 0 lLen = lLenText 'get whole text up to the end of the string Case 0 lLen = lLenText + 1 Case Else lLen = -lLenText 'get whole text up to the start of the string End Select End If Dim lMidStart As Long 'start of the string to return, we intend to use the orginal Mid-function If lStart < 0 Then lMidStart = lLenText + 1 + lStart 'convert negative position to corresponding positive position Else lMidStart = lStart End If Dim lMidLen As Long 'length of the string to return If lLen < 0 Then 'the string to return is left to lMidStart lMidStart = lMidStart + 1 + lLen 'start of the string lMidLen = -lLen Else 'the string to return is right to lMidStart lMidLen = lLen End If If lMidStart < 1 Then 'start still negative, lMidLen = lMidLen + lMidStart - 1 'length must be shortened, so that we cab use thr original Mid-function lMidStart = 1 'the string to return starts from the first position End If 'if lMidLen isn't positiv, return an empty string If lMidLen < 1 Then 'we can't give a negative length to the original Mid, because ist would return the whole string sText Middle = "" Else 'ready to use the original Mid Middle = Mid(sText, lMidStart, lMidLen) End If If IsMissing(sInsert) Then Exit Function 'don't change the string sText, so we are done sText = Left(sText, lMidStart - 1) & sInsert & Mid(sText, lMidStart + lMidLen) End Function
MID function definition is here http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part2.html#__RefHeading__1018864_715980110
Thanks for the link. I don't want to change the signature of Mid. I did this in the Middle function only because I don't know whether and how to return an l-value using BASIC. I assume there is no code which makes use of the undefined behaviour, if you use negative length. However I admit that my proposal might break existing code which - through error handling - relies on the fact that Mid throws an error when given a negative start position. Here's my third try Sub MiddleDemo 'The Mid-function is less then optimal 'Problems are '- a negative length is treated like no length given '- a start position of 0 results in error 5 '- a negative start positions returns !br0ken!! Dim sText As String sText = "abcdefghijkl" Print "The Mid-function is " & Mid(sText, -1) Print Middle(sText, 0, 3) 'the first two characters Print Middle(sText, -1, -4) 'the last four characters Call Middle(sText, 6, -3, "45678") 'replace three charactes counted to the left from the sixth position Print sText End Sub Function Middle(sText As String, Optional lStart As Long, Optional lLen As Long, Optional sInsert As String) As String 'like Mid, but takes negative lLen which runs from left to right 'also negative lStart which are counted to the left, from the 'last position in the String i.e. the last Position is -1 'On Error GoTo Err_Middle If IsMissing(lStart) Then lStart = 1 Dim lLenText As Long lLenText = Len(sText) If IsMissing(lLen) Then Select Case lStart Case > 0 lLen = lLenText 'get whole text up to the end of the string Case 0 lLen = lLenText + 1 Case Else 'I don't know if this is a godd idea, or if it still should be lLen = lLenText lLen = -lLenText 'get whole text up to the start of the string End Select End If 'we intend to use the orginal Mid-function Dim lMidStart As Long 'so we calculate the start of the string to return in a coordinate system, which Mid understands If lStart < 0 Then lMidStart = lLenText + 1 + lStart 'convert negative position to corresponding positive position Else lMidStart = lStart End If Dim lMidLen As Long 'length of the string to return If lLen < 0 Then 'the string to return is left to lMidStart lMidStart = lMidStart + 1 + lLen 'start of the string lMidLen = -lLen Else 'the string to return is right to lMidStart lMidLen = lLen End If If lMidStart < 1 Then 'start still negative, lMidLen = lMidLen + lMidStart - 1 'length must be shortened, so that we can use the original Mid-function lMidStart = 1 'the string to return starts from the first position End If 'if lMidLen isn't positiv, return an empty string If lMidLen < 1 Then 'we can't give a negative length to the original Mid, because it would return the whole string sText Middle = "" Else 'ready to use the original Mid Middle = Mid(sText, lMidStart, lMidLen) End If If IsMissing(sInsert) Then Exit Function 'don't change the string sText, so we are done sText = Left(sText, lMidStart - 1) & Left(sInsert, lMidLen) & Mid(sText, lMidStart + lMidLen) Exit_Middle: Exit Function Err_Middle: Print StdErrMsg & CStr(Err) & " in Line " & CStr(Erl) & Chr$(13) & Chr$(10) & Error$ & " StringMod.Middle" Resume Next End Function
(In reply to ge.huber from comment #0) > The Mid-function is less then optimal. > I don't have any strong feelings about whether the Mid function needs improvement, but I'm always in favor of better interfaces for programming. Except for small snippets, please toss code into a repository somewhere. Gitorious and GitHub are both good options, and will let you improve the code without pasting and re-pasting long comments here. As a bonus, you get indentation support, syntax highlighting, and all of those good things for free! As Raal points out, the Mid function is defined in some OASIS docs covering the ODF spec, so changes should go up to them. That being said, it seems pretty tough to just go suggest something to the OASIS ODF TC, so I'm not opposed to some conversation here about whether this is a good idea or not, and what specific changes might be helpful. Status -> NEW
(In reply to Robinson Tryon (qubit) from comment #4) > > As Raal points out, the Mid function is defined in some OASIS docs covering > the ODF spec, so changes should go up to them. That being said, it seems > pretty tough to just go suggest something to the OASIS ODF TC, Oh. I see. I'm not opposed to being referred to the proper addressee, just don't know how to communicate with them. That's assumed they let me at all. However I'm not sure if OASIS is concerned here. I'm talking about the Mid function in BASIC. Is it necessarily bound to the MID function used in Calc documents? > so I'm not > opposed to some conversation here about whether this is a good idea or not, > and what specific changes might be helpful. As I already admitted introducing a negative start might in theory break existing code. However there seems to be nothing in the definition which tells what to do with negative length. So of course whoever implemented the current behaviour was well within his rights. Actually he could have tried to start a game of nethack. ;-) http://everything2.com/title/%2523pragma However one might move beyond this point and start to make something potentially useful of it.
Oh f*! What nonsense did I just write here? Well. Mid (i.a. the BASIC function) does not conform to OASIS MID (i.e.the Calc function) definition. According to OASIS "If Start < 0, it returns an Error." However Print "The Mid-function is " & Mid("quite ok.", -1) doesn't. Hope i got this right now.
Please note that the ODF OpenFormula (ODFF) spreadsheet function MID() as defined in http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part2.html#MID is unrelated to the BASIC function Mid() which this issue is about.
(In reply to Eike Rathke from comment #7) > Please note that the ODF OpenFormula (ODFF) spreadsheet function MID() as > defined in > http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part2. > html#MID is unrelated to the BASIC function Mid() which this issue is about. Clarifying Summary
Should we change the behaviour of the mid function or does it brake basic compatibility?
can you share this for website http://gettingoveritapks.com