When using methods of selecting text and restoring selected text in a page, I have found that running execCommand('insertHTML... inbetween causes the stored selection to break.
This is a sample of how the text is selected and restored.
// Get Selection
var sel = window.getSelection().getRangeAt(0);
// Clear Selections
window.getSelection().removeAllRanges();
// Restore Selection
window.getSelection().addRange(sel)
This works fine, however once you run execCommand('insertHTML.. the selections endOffset sets itself to the same value as the selections startOffset
Is there a reason for this? More importantly is there a way round this?
A full example of the bug, complete with some basic console logging can be seen here.
http://jsfiddle.net/blowsie/Y8pJ7/
The objective of this fiddle is to select text , transform it to uppercase and then reselect the text.
How best to save and restore the selection really depends on what you're doing. For your specific example, where existing text is just having its case transformed, I'd suggest a character index-based approach, such as https://stackoverflow.com/a/5596688/96100 (although that answer requires Rangy, but can be trivially changed not to require it: http://jsfiddle.net/Y8pJ7/8).
For some other cases, a better approach is to use invisible marker elements at the start and end of the selection, which is the approach taken by the selection save/restore module of Rangy (disclosure: I am Rangy's author).
UPDATE 18 June 2012
Rangy now has character offset-based save and restore of selections and ranges via a new TextRange module (demo).
Related
In Outlook 2010 I have a UserForm with a ListBox.
This ListBox has 4 columns where I show a list of attachments (the columns "File-Name", "File-Type", "File-Size" and "Target-Directory".
Unfortunately the ListBox is restricted in layout functionality, the user can not adjust the column width at runtime (so I have to specify the width of the columns by design).
Because the file path can be quiet long, I set the width of the last column to 999 Pt.
So my ListBox has a horizontal scrollbar.
I want to have the following layout changes to my ListBox:
Add column headers
Change the alignment of a column to right-aligned
Optional: allow the user to sort the list by any column
Optional: allow the user to sort change the width of any column
Optional: show a grid in the ListBox
For 1. I found some answers that this is very complicated and I should use static labels above the list instead.
This is not possible, because my ListBox can be scrolled horizontally.
Is the ListBox really so restricted or is #1 and #2 possible somehow?
I know that there are foreign components available, but I am not allowed to buy any component.
And my solution should work at my colleagues too, so they would also have to install these components.
I have been experimenting with possible solutions to your problem. I think I have taken the listbox approach as far as it will go so I will share what I have discovered.
I can find nothing on the web to suggest that anyone believes you can have listbox column headers without using property RowSource. To use RowSource, you set it to an Excel range.
I got Outlook to create an Excel workbook and to write some data to it. Unfortunately, I could not find any way of getting an Outlook user form to access an Excel range. The syntax for setting RowSource is:
ListBox1.RowSource = "Emails!A2:D20"
This is not the standard syntax for a range and I have failed to discover any method of extending it to include a workbook name.
Jonah_Hess describes an interesting approach in https://stackoverflow.com/a/43381634/973283. He has two list boxes. One is a one-line listbox that contains the headings and the other contains the data. The two listboxes are set to the same number of columns with the same widths. This gives an attractive appearance but if you scroll the data listbox, the headings listbox does not scroll with it. This is not really any different from placing labels above a single listbox.
I tried putting the headings and the data list boxes in a frame and scrolling the frame but could not get it to work. I have used frames with VB user forms but the functionality is very different so there are no lessons learnt that I could bring to a VBA user form. Perhaps someone more familiar with VBA frames could get this approach to work.
I gave up trying to get a solution in Outlook. An Excel macro can access Outlook data so I tried that approach.
I created a macro-enabled workbook. Within it, I have two forms both of which fill the screen to conceal the worksheet. The first form just says: “Please wait while I load data from Outlook”. I am not clear about the data on your form so I imported selected details from a folder full of junk emails which I wrote to a worksheet. I sized the columns for the list box to match those for the worksheet. The result was:
The text is a little small but I think it is readable. The listbox at the bottom allows me to select emails for different periods. Long ago I had problems with RowSource which meant I could change the values in the range but I could not change the size of the range. I have either managed to avoid that problem today or it was a bug that has been fixed.
You can see that the headings are displayed. The columns are a little wide but I consider them to be a reasonable first approximation. Options to change the widths would be easy to implement.
The changes you ask for:
Add column headers. Done
Change the alignment of a column to right-aligned. Possible but difficult. You would need to pad the text with an appropriate number of leading spaces.
Optional: allow the user to sort the list by any column. The data is in a worksheet so easy.
Optional: allow the user to change the width of any column. I have set the column widths at runtime to show it is possible.
Optional: show a grid in the ListBox. Not possible.
If the above is interesting, I could show you all my code and instruct you on creating the forms so you could duplicate my experiment. Alternately, I could just explain: how I imported the Outlook data to Excel, how I included the column headings and how I set the column widths.
I cannot find anything to suggest that anything better can be achieved with listboxes.
An alternative approach is to use a grid of labels. This can give an attractive appearance and one or more columns could be right-aligned. Using the Controls property of the user form, you can treat the grid as a two-dimensional array. I have used this technique long ago and found it attractive and not particularly difficult.
In order to set the alignment of a specific column to the right, trying the opposite way might help you:
Set TextAlign attribute of the listbox to "3-fmTextAlignRight".
Add spaces at the END of the each data in the column of sourcearray, which you want to align LEFT. The number of added spaces should be so large as to exceed the width of the column in which the data appears. You don't have to mind whether the number fits to the columnwidth (overflown spaces do no harm). You may prefer to use & String(30, " ") instead (30 is just for example) .
If added spaces seem to be wholly ignored (i.e. data appear right-aligned only), further add any single character (such as "_") at the end of the spaces.
This is a cosmetic solution, but works when seeing left-aligned figures is too annoying.
After doing the above, please be careful when selecting from the list (trimming the added spaces, keeping BoundColumn data intact, etc.).
This trick works for both Excel and Outlook (not sure for other applications).
Test result in Outlook VBA (...trailing 50 spaces are added to data in column 1 and 4.)
Hope this helps.
I'm having to convert some documents which had been built in OpenOffice over to word, and one thing which seems overly complicated in Word is conditional text. OO had some features which made this a breeze, but I'm thinking I'm missing something in Word.
For more simple pieces of text I've used the {IF {DOCVARIABLE xxxx} = ...} method which seems to work well with single lines of text.
For longer blocks of text I've tried using a similar method but inserting an Autotext block. This works well if the content is static, but if the content I'm inserting needs to be edited, updating the document ends up replacing any changes with the Autotext block. So this method won't work for parts of my document.
Most of the search results I'm seeing use some variation of the two methods above. Is there something else I can use which allows blocks of text, possibly including tables, to be conditionally inserted or hidden and also editable?
Macros are okay since this is how I'm setting various DOCVARIABLE parameters in the document.
I'm using Word 2016 on Windows 7.
After doing more experimenting, it looks like I can use bookmarks to do what I need.
I can select the block of text I want to conditionally show/hide, then create a bookmark for the selection.
Then in my macro I can hide the section when necessary with:
ActiveDocument.Bookmarks("MyBookmarkName").Range.Font.Hidden = True
or show it again using False instead of True. This seems to hide tables and other things within that block of text. I'd love it if the Word developers would add some of the features for this type of thing which are in OpenOffice.
I have a PDF form that I'm filling out with data using progress-4gl. To date, I've been only filling in text fields using the following syntax:
put stream stream1 unform
"^global CHX_SINGLE_CE_PLAN3" skip(0)
"X" skip
CHX_SINGLE_CE_PLAN3 is the field name...
This code works when dealing with text fields but I'm trying to check a box instead of fill in a text field. I cannot find any documentation on this. Is checking a box on a fillable pdf form even possible with 4gl?
As far as I remember PDF Include has support for filling fillable forms. Whilst it's probably a bit over the top in terms of what you want to achieve, it's an open source project and so you may well find the answer to your question within the code itself.
Here's a link to the project page: http://www.oehive.org/pdfinclude
I discovered the answer, which I thought I had already tried before asking this question. The answer is you need to pass the value "Yes" (with capital "Y") in order to check the checkbox. The correct code in this instance is:
put stream stream1 unform
"^global CHX_SINGLE_CE_PLAN3" skip(0)
"Yes" skip
I believe this is the case no matter which language you're using
Background:
How: I suspect that this is a glitch within Google Form (submission process)/Spreadsheet, but may be part of the Date conversion utility of the Spreadsheet interface (and is an intended feature).
When entering a format in a text box in Google Forms, there is some sort of communication error between the Form submit and Response Spreadsheet, or pre-processing of the Form's data before it is sent to the spreadsheet. The glitch only seems to happen for data in a text field of the format ##:## TEXT where TEXT contains no '.' characters. For example: 4:15 pm will reproduce the glitch, but 4:15 p.m and 4:15 p.m. will not.
Result: An apostrophe character is added to the beginning of the string when it is put into the Spreadsheet (i.e. '4:15 pm) which throws off several sub-systems I have in place that use that time data. Here are two screenshots (sorry for the bad sizing on the second):
I'm 99% certain that the glitch is caused by the ##: combination.
Temporary Fix?: The real question is... how might I go about removing that pesky apostrophe before I start manipulating the time data? I know how to getValue() of a cell/Range. Assume I have the value of a cell in the following manner:
var value = myRange.getValue();
// value = '4:15 pm
How can I go about processing that value into 4:15 pm? A simple java function could be
value = value.substring(1); // Assuming "value" is a String
But in Google App Scripts for Spreadsheets, I don't know how I would do that.
Post-Script: It is necessary to post-process this data so that I don't have to lecture university faculty in the language department about inputting time format correctly in their forms.
Thanks in advance to those who can help!
How can I go about processing that value into 4:15 pm? A simple java
function could be
value = value.substring(1); // Assuming "value" is a String But in
Google App Scripts for Spreadsheets, I don't know how I would do that.
Google Apps Scripts uses Javascript which has the exact same method.
value = value.substring(1);
should return all except the first character.
More about Javascript substring at: http://www.w3schools.com/jsref/jsref_substring.asp
If you remove the ' in the spreadsheet cell the spreadsheet interface will convert this entry to a date object.
This might (or not) be an issue for you so maybe you should handle this when you read back your data for another use...
It doesn't happen when text is different (for example with P.M) simply because in this case the ' is not necessary for the spreadsheet to keep it as a string since the spreadsheet can't convert it to a date object (time value).
Artificial intelligence has its bad sides ;-)
edit :
You cant do this in an onFormSubmit triggered function using the javascript substring() you mentioned. If you're not familiar with that, here is the way to go :
To run a script when a particular action is performed:
Open or a create a new Spreadsheet.
Click the Unsaved Spreadsheet dialog box and change the name.
Choose Tools > Script Editor and write the function you want to run.
Choose Resources > Current project's triggers. You see a panel with
the message No triggers set up. Click here to add one now.
Click the link.
Under Run, select the function you want executed by the trigger.
Under Events, select From Spreadsheet.
From the next drop-down list, select On open, On edit, or On form
submit.
Click Save.
see doc here and here
I'd like to be able to create a page element which I can feed text and it will form itself into the preferred layout. For instance:
{MACRO DocumentIntro("Introduction to Business Studies", "FP015", "Teachers' Guide")}
with that as a field, the output should be a line, the first two strings a certain size and font, centred, another line and then the third string fonted, sized and centred.
I know that's sort of TeX-like and perhaps beyond the scope of VBA, but if anyone's got any idea how it might be possible, please tell!
EDIT:
Ok, if I put the required information into Keyword, as part of the document properties, with some kind of unique separator, then that gets that info in, and the info will be unique to each document. Next one puts a bookmark where the stuff is going to be displayed. Then one creates an AutoOpen macro that goes to that bookmark, pulls the relevants out of the keywords, and forms the text appropriately into the bookmark's .Selection.
Is that feasible?
You're certainly on the right track here for a coding solution. However, there is a simpler way with no code - this is the type of scenario that Content Controls in Word 2007 were built for and with Fields/Properties, you can bind to content controls (CC). These CC can hold styles (like centered, bold, etc.). No VBA required.
The very easiest thing to do is to pick 3 built-in document properties that you will always want these to be. For example, "Title" could be your first string, "Subject" your second string and "Keywords" your third. Then, just go to the Insert ribbon, Quick Parts, Document Properties and insert, place and format those how you like. Then go to Word's start button (the orb thingy) and then under Prepare choose Properties. Here you can type, for example "Introduction to Business Studies", into the Title box and then just deselect it somehow (like click in another box). The Content Control for Title will be filled in automatically with your text.
If you want to use this for multiple files, just create this file as a .dotx (after CC insertion/placement/formatting and before updating the Document Properties' text). Then every time all you'll have to do is set these three properties with each new file.
Well, yes, it did turn out to be feasible.
Sub autoopen()
Dim sKeywords As String
sKeywords = ActiveDocument.BuiltInDocumentProperties(4)
ActiveDocument.Bookmarks("foo").Select
Selection.Text = sKeywords
End Sub
Okay, I have some filling out to do, but at least the guts of it are there.