Friday, January 9, 2009

Using MapSubstring() to edit strings

The MapSubstring() function is a powerful alternative to using nested Replace() or PurgeChar() functions.

MapSubstring(), unlike it's siblings ApplyMap() and Map, will apply multiple mappings from the mapping table. Here's an example.

ReplaceMap:
MAPPING LOAD * INLINE [

char replace
) \
) \
" \
, \
/ \
- \
] (delimiter is ' ')
;


TestData:
LOAD
*,
MapSubString('ReplaceMap', data) as ReplacedString

;
LOAD * INLINE [

(415)555-1234
(415)543,4321
"510"123-4567
/925/999/4567
] (delimiter is ' ')
;


In field "ReplacedString", all the characters matching the first field of the map ("char") are replaced with a backslash as shown in this table. This makes it ready for parsing with a function like SubField().



Another usage is an alternative to nested PurgeChar() to remove multiple characters. A blank is used as the mapping character. For example:

PurgeMap:
MAPPING LOAD * INLINE [

char replace
)
)
"
,
/
-
] (delimiter is ' ')
;



MapSubString('PurgeMap', Data)
will produce results like this:



-Rob

Monday, January 5, 2009

The design of grouped objects

I recently submitted a feature request to Qliktech requesting "grouped objects". There are a number of issues to consider when thinking about how grouped objects should be implemented in QV.

You are probably familiar with the idea of grouped objects. It's a feature commonly available in graphics authoring programs Select a set of objects and mark them as "grouped". Operations such as Move or Resize then apply to the group.

The problems I'm trying to address by asking for grouped objects:

  • When two or more objects are logically related, it's would be useful if they could be minimized or restored together.


  • It's a common practice to layer objects upon one another to produce an effect that is not available with a single object. For example, Stephen Few's Bullet Graph is commonly implemented in QV as a chart upon a chart. The Qliktech demo "Finance Controlling" uses this technique. Another common use case is placing a transparent text box on a chart to provide helptext, or a button to provide action.

    Currently, if you layer objects, you also have to prohibit the user from moving or resizing the objects. If not, user move or resize operations may cause the objects to be misaligned.

If QV would let me select a set of objects and mark them as a "group", how should the group of objects respond to various user actions?

Let's first consider a group of two objects that are related, but do not overlap on the screen. For example, a straight table and text box. The text box contains some summary data from the table. Here's are some possible behaviors:

  1. If the user moved any object, all objects would move as a group, maintaining relative position to one another.
  2. If the user resizes one object, all objects will resize proportionally and maintain position relative one another.
  3. If the user maximizes one object, the group will enlarge proportionally to fill the screen.

Let's consider another case. Two overlayed bar charts are used to create a Bullet Graph. One chart also contains a button in the caption area. It's critical that the overlayed charts maintain position and size relative to one another. The button is a fixed artifact that should not resize but must remain in the "correct" position. How should the behavior differ from the example above?

If one of the charts is resized or maximized, both charts must resize. The button should not resize. This could be controlled by use of the "allow move/resize" property of each object. If the property is checked, the object will participate in a group resize. If unchecked, the object will not resize with the group. However, all objects will maintain relative position.

What specifically, is "relative position"? I define it as the "x,y pixel distance from the nearest corner of a parent object. The parent is the object in the same group who's corner is closest to the child object". An object can only be relative to one parent object. The parent may change after a resize operation.

It would simplify the grouping process if the "Allow Move/Size" property were split into two separate properties -- "Allow Move" and "Allow Size". In the chart & button example, all objects would "Allow Move" but only the charts would "Allow Size".

Your comments and improvements on this proposal are welcome.

-Rob

Update 01/09/2009: What about Object "Print" and "Copy To Clipboard -> Image" functions? My proposal would be to include all objects that share a pixel with the right-clicked object.