Skip to main content
Glama

get_app_field

Retrieve values of a specific field from a Qlik Sense app with pagination, wildcard search, and case-sensitive matching options.

Instructions

Return values of a single field from app with pagination and wildcard search (supports * and %).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
app_idYesApplication GUID
case_sensitiveNoCase sensitive matching for search_string
field_nameYesField name
limitNoMax values to return (default: 10, max: 100)
offsetNoOffset for pagination (default: 0)
search_numberNoWildcard numeric search mask (* and % supported)
search_stringNoWildcard text search mask (* and % supported), case-insensitive by default

Implementation Reference

  • Main execution handler for the 'get_app_field' tool. Processes input parameters (app_id, field_name, limit, offset, search_string, search_number, case_sensitive), connects to Qlik Engine API, fetches raw field values using get_field_values helper, applies wildcard text/numeric search filters, performs client-side pagination, and returns sliced field values.
    elif name == "get_app_field": app_id = arguments["app_id"] field_name = arguments["field_name"] limit = arguments.get("limit", 10) offset = arguments.get("offset", 0) search_string = arguments.get("search_string") search_number = arguments.get("search_number") case_sensitive = arguments.get("case_sensitive", False) if limit is None or limit < 1: limit = 10 if limit > 100: limit = 100 if offset is None or offset < 0: offset = 0 def _wildcard_to_regex(pattern: str, case_sensitive_flag: bool) -> Any: import re escaped = re.escape(pattern).replace("\\*", ".*").replace("%", ".*") regex = f"^{escaped}$" return re.compile(regex, 0 if case_sensitive_flag else re.IGNORECASE) def _get_values(): try: self.engine_api.connect() app_result = self.engine_api.open_doc_safe(app_id, no_data=False) app_handle = app_result.get("qReturn", {}).get("qHandle", -1) if app_handle == -1: return {"error": "Failed to open app"} fetch_size = max(limit + offset, 500) if fetch_size > 5000: fetch_size = 5000 field_data = self.engine_api.get_field_values(app_handle, field_name, fetch_size, include_frequency=False) values = [v.get("value", "") for v in field_data.get("values", [])] if search_string: rx = _wildcard_to_regex(search_string, case_sensitive) values = [val for val in values if isinstance(val, str) and rx.match(val)] if search_number: rxn = _wildcard_to_regex(search_number, case_sensitive) filtered = [] for idx, vobj in enumerate(field_data.get("values", [])): cell_text = vobj.get("value", "") qnum = vobj.get("numeric_value", None) if qnum is not None: if rxn.match(str(qnum)) or rxn.match(str(cell_text)): filtered.append(cell_text) values = filtered sliced = values[offset:offset + limit] return {"field_values": sliced} except Exception as e: return {"error": str(e)} finally: self.engine_api.disconnect() result = await asyncio.to_thread(_get_values) return [TextContent(type="text", text=json.dumps(result, indent=2, ensure_ascii=False))]
  • Tool registration and input schema definition for 'get_app_field' in the list_tools() handler. Defines the tool name, description, and JSON schema for parameters including app_id (required), field_name (required), pagination (limit/offset), and search options (search_string, search_number, case_sensitive).
    Tool( name="get_app_field", description="Return values of a single field from app with pagination and wildcard search (supports * and %).", inputSchema={ "type": "object", "properties": { "app_id": {"type": "string", "description": "Application GUID"}, "field_name": {"type": "string", "description": "Field name"}, "limit": {"type": "integer", "description": "Max values to return (default: 10, max: 100)", "default": 10}, "offset": {"type": "integer", "description": "Offset for pagination (default: 0)", "default": 0}, "search_string": {"type": "string", "description": "Wildcard text search mask (* and % supported), case-insensitive by default"}, "search_number": {"type": "string", "description": "Wildcard numeric search mask (* and % supported)"}, "case_sensitive": {"type": "boolean", "description": "Case sensitive matching for search_string", "default": False} }, "required": ["app_id", "field_name"], } ),
  • Core helper method in QlikEngineAPI class that creates a ListObject session object for the specified field, fetches up to max_values field values via GetLayout, extracts value/text/numeric/state/frequency data from qDataPages, and cleans up the session object. Called by server.py handler with include_frequency=False.
    def get_field_values( self, app_handle: int, field_name: str, max_values: int = 100, include_frequency: bool = True, ) -> Dict[str, Any]: """Get field values with frequency information using ListObject.""" try: # Use correct structure list_def = { "qInfo": {"qId": f"field-values-{field_name}", "qType": "ListObject"}, "qListObjectDef": { "qStateName": "$", "qLibraryId": "", "qDef": { "qFieldDefs": [field_name], "qFieldLabels": [], "qSortCriterias": [ { "qSortByState": 0, "qSortByFrequency": 1 if include_frequency else 0, "qSortByNumeric": 1, "qSortByAscii": 1, "qSortByLoadOrder": 0, "qSortByExpression": 0, "qExpression": {"qv": ""}, } ], }, "qInitialDataFetch": [ {"qTop": 0, "qLeft": 0, "qHeight": max_values, "qWidth": 1} ], }, } # Create session object - use correct parameter format result = self.send_request( "CreateSessionObject", [list_def], handle=app_handle ) if "qReturn" not in result or "qHandle" not in result["qReturn"]: return {"error": "Failed to create session object", "response": result} list_handle = result["qReturn"]["qHandle"] layout = self.send_request("GetLayout", [], handle=list_handle) # Correct path to qListObject - it's in qLayout if "qLayout" not in layout or "qListObject" not in layout["qLayout"]: # Clean up object before returning error try: self.send_request( "DestroySessionObject", [f"field-values-{field_name}"], handle=app_handle, ) except: pass return {"error": "No list object in layout", "layout": layout} list_object = layout["qLayout"]["qListObject"] values_data = [] # Process data for page in list_object.get("qDataPages", []): for row in page.get("qMatrix", []): if row and len(row) > 0: cell = row[0] value_info = { "value": cell.get("qText", ""), "state": cell.get( "qState", "O" ), # O=Optional, S=Selected, A=Alternative, X=Excluded "numeric_value": cell.get("qNum", None), "is_numeric": cell.get("qIsNumeric", False), } # Add frequency if available if "qFrequency" in cell: value_info["frequency"] = cell.get("qFrequency", 0) values_data.append(value_info) # Get general field information field_info = { "field_name": field_name, "values": values_data, "total_values": list_object.get("qSize", {}).get("qcy", 0), "returned_count": len(values_data), "dimension_info": list_object.get("qDimensionInfo", {}), "debug_info": { "list_handle": list_handle, "data_pages_count": len(list_object.get("qDataPages", [])), "raw_size": list_object.get("qSize", {}), }, } try: self.send_request( "DestroySessionObject", [f"field-values-{field_name}"], handle=app_handle, ) except Exception as cleanup_error: field_info["cleanup_warning"] = str(cleanup_error) return field_info

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bintocher/qlik-sense-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server