Multiple variable declarations [closed] - vmware

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have a script which I use it for multiple tasks like
Create Folder in vSphere
Create ResourcePools
Create a VM (VMware)
Configure IP/DNS
Add it to domain, …
For this I need multiple inputs needed like VM name, vCenter Server name, userid, password, etc. How do I declare the input variables externally (separate from Main script) and also make it generic in look.
I tried using below procedure but it gives me call depth overflow error.
VARIABLE_DECLARATION.ps1:
VariableDeclaration = #{
[CmdletBinding()]
Param (
[Parameter(Mandatory=$True)]
[Parameter(ValueFromPipeline=$true)]
[int]$CustomerCID = '10000';
[string]$CustomerName = "ABCcorp";
[string]$vCenterName = "vCenter.ABCcorp.com";
[string]$vCenterUserName = "administrator#vsphere.local";
[string]$vCenterPassword = "ABCcorp123!";
[string]$CustomerPODLocation = "VW1";
[string]$DatacenterName = "ABCcorpDC";
[string]$ClusterName = "ABCcorpcluster";
[string]$InfraResourcePoolName = ($CustomerCID + "-" + $CustomerName + "-" + "Infrastructure");
[string]$DesktopResourcePoolName = ($CustomerCID + "-" + $CustomerName + "-" + "Desktop");
[string]$CustomerFolderName = ($CustomerCID + "-" + $CustomerName);
[string]$ConnectionType = "xConnect";
[int]$VLANID = '237';
[string]$CustomerDVPortGroupName = ($CustomerPODLocation + "-" + $ConnectionType + "-" + $CustomerCID + "-" + $CustomerName + "-" + $VLANID);
[int]$NumberofPorts = '1024';
[string]$AD1computername = ($CustomerCID + "-RADSVR01-v" + $CustomerName + ".vdi");
[string]$AD2computername = ($CustomerCID + "-RADSVR02-v" + $CustomerName + ".vdi");
[string]$sourcetemplate = "BaseWin2012R2";
[string]$description = "ABCcorp Infra Systems";
[string]$OSCustomizationspec = "ABCcorp";
[string]$AD1IP = "10.0.0.10";
[string]$AD2IP = "10.0.0.11";
[string]$SNM = "255.255.255.0";
[string]$DG = "10.0.0.1";
[string]$DNS = "10.0.0.2";
[string]$HostUsername = "root";
[string]$HostPassword = (ConvertTo-SecureString -String "ABCcorp123" -AsPlainText -Force);
[string]$HostCredential = (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $HostUsername, $HostPassword)
)
}

PowerShell parameter definition doesn't work that way. Create a function for each of your tasks with the parameters required for that specific function/task. To make the functions available put them in a script and dot-source it, or put them in a module and load that module.
Example for dot-sourcing a PowerShell script:
vm-functions.ps1:
function New-VSphereFolder {
Param(
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[string]$FolderName,
[Parameter(Mandatory=$false, ValueFromPipeline=$true)]
[string]$vCenterName = "vCenter.ABCcorp.com",
[Parameter(Mandatory=$false, ValueFromPipeline=$true)]
[string]$Username = "administrator#vsphere.local",
[Parameter(Mandatory=$false, ValueFromPipeline=$true)]
[string]$Password = "ABCcorp123!",
...
)
...
}
function New-ResourcePool {
...
}
Dot-source the script the script to make the functions available in the current context, then use whichever function you need:
PS C:\> . C:\path\to\vm-functions.ps1
PS C:\> New-VSphereFolder -FolderName ...
...
For further information about parameters in PowerShell scripts/functions see here and here.

Related

Is there a way to generate the AWS Console URLs for CloudWatch Log Group filters?

I would like to send my users directly to a specific log group and filter but I need to be able to generate the proper URL format. For example, this URL
https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#logsV2:log-groups/log-group/
%252Fmy%252Flog%252Fgroup%252Fgoes%252Fhere/log-events/$3FfilterPattern$3D$255Bincoming_ip$252C$2Buser_name$252C$2Buser_ip$2B$252C$2Btimestamp$252C$2Brequest$2B$2521$253D$2B$2522GET$2B$252Fhealth_checks$252Fall$2B*$2522$252C$2Bstatus_code$2B$253D$2B5*$2B$257C$257C$2Bstatus_code$2B$253D$2B429$252C$2Bbytes$252C$2Burl$252C$2Buser_agent$255D$26start$3D-172800000
will take you to a log group named /my/log/group/goes/here and filter messages with this pattern for the past 2 days:
[incoming_ip, user_name, user_ip , timestamp, request != "GET /health_checks/all *", status_code = 5* || status_code = 429, bytes, url, user_agent]
I can decode part of the URL but I don't know what some of the other characters should be (see below), but this doesn't really look like any standard HTML encoding to me. Does anyone know a encoder/decoder for this URL format?
%252F == /
$252C == ,
$255B == [
$255D == ]
$253D == =
$2521 == !
$2522 == "
$252F == _
$257C == |
$2B == +
$26 == &
$3D == =
$3F == ?
First of all I'd like to thank other guys for the clues. Further goes the complete explanation how Log Insights links are constructed.
Overall it's just weirdly encoded conjunction of an object structure that works like that:
Part after ?queryDetail= is object representation and {} are represented by ~()
Object is walked down to primitive values and the latter are transformed as following:
encodeURIComponent(value) so that all special characters are transformed to %xx
replace(/%/g, "*") so that this encoding is not affected by top level ones
if value type is string - it is prefixed with unmatched single quote
To illustrate:
"Hello world" -> "Hello%20world" -> "Hello*20world" -> "'Hello*20world"
Arrays of transformed primitives are joined using ~ and as well put inside ~() construct
Then, after primitives transformation is done - object is joined using "~".
After that string is escape()d (note that not encodeURIComponent() is called as it doesn't transform ~ in JS).
After that ?queryDetail= is added.
And finally this string us encodeURIComponent()ed and as a cherry on top - % is replaced with $.
Let's see how it works in practice. Say these are our query parameters:
const expression = `fields #timestamp, #message
| filter #message not like 'example'
| sort #timestamp asc
| limit 100`;
const logGroups = ["/application/sample1", "/application/sample2"];
const queryParameters = {
end: 0,
start: -3600,
timeType: "RELATIVE",
unit: "seconds",
editorString: expression,
isLiveTrail: false,
source: logGroups,
};
Firstly primitives are transformed:
const expression = "'fields*20*40timestamp*2C*20*40message*0A*20*20*20*20*7C*20filter*20*40message*20not*20like*20'example'*0A*20*20*20*20*7C*20sort*20*40timestamp*20asc*0A*20*20*20*20*7C*20limit*20100";
const logGroups = ["'*2Fapplication*2Fsample1", "'*2Fapplication*2Fsample2"];
const queryParameters = {
end: 0,
start: -3600,
timeType: "'RELATIVE",
unit: "'seconds",
editorString: expression,
isLiveTrail: false,
source: logGroups,
};
Then, object is joined using ~ so we have object representation string:
const objectString = "~(end~0~start~-3600~timeType~'RELATIVE~unit~'seconds~editorString~'fields*20*40timestamp*2C*20*40message*0A*20*20*20*20*7C*20filter*20*40message*20not*20like*20'example'*0A*20*20*20*20*7C*20sort*20*40timestamp*20asc*0A*20*20*20*20*7C*20limit*20100~isLiveTrail~false~source~(~'*2Fapplication*2Fsample1~'*2Fapplication*2Fsample2))"
Now we escape() it:
const escapedObject = "%7E%28end%7E0%7Estart%7E-3600%7EtimeType%7E%27RELATIVE%7Eunit%7E%27seconds%7EeditorString%7E%27fields*20*40timestamp*2C*20*40message*0A*20*20*20*20*7C*20filter*20*40message*20not*20like*20%27example%27*0A*20*20*20*20*7C*20sort*20*40timestamp*20asc*0A*20*20*20*20*7C*20limit*20100%7EisLiveTrail%7Efalse%7Esource%7E%28%7E%27*2Fapplication*2Fsample1%7E%27*2Fapplication*2Fsample2%29%29"
Now we append ?queryDetail= prefix:
const withQueryDetail = "?queryDetail=%7E%28end%7E0%7Estart%7E-3600%7EtimeType%7E%27RELATIVE%7Eunit%7E%27seconds%7EeditorString%7E%27fields*20*40timestamp*2C*20*40message*0A*20*20*20*20*7C*20filter*20*40message*20not*20like*20%27example%27*0A*20*20*20*20*7C*20sort*20*40timestamp*20asc*0A*20*20*20*20*7C*20limit*20100%7EisLiveTrail%7Efalse%7Esource%7E%28%7E%27*2Fapplication*2Fsample1%7E%27*2Fapplication*2Fsample2%29%29"
Finally we URLencode it and replace % with $ and vois la:
const result = "$3FqueryDetail$3D$257E$2528end$257E0$257Estart$257E-3600$257EtimeType$257E$2527RELATIVE$257Eunit$257E$2527seconds$257EeditorString$257E$2527fields*20*40timestamp*2C*20*40message*0A*20*20*20*20*7C*20filter*20*40message*20not*20like*20$2527example$2527*0A*20*20*20*20*7C*20sort*20*40timestamp*20asc*0A*20*20*20*20*7C*20limit*20100$257EisLiveTrail$257Efalse$257Esource$257E$2528$257E$2527*2Fapplication*2Fsample1$257E$2527*2Fapplication*2Fsample2$2529$2529"
And putting it all together:
function getInsightsUrl(queryDefinitionId, start, end, expression, sourceGroup, timeType = 'ABSOLUTE', region = 'eu-west-1') {
const p = m => escape(m);
const s = m => escape(m).replace(/%/gi, '*');
const queryDetail
= p('~(')
+ p("end~'")
+ s(end.toUTC().toISO()) // converted using Luxon
+ p("~start~'")
+ s(start.toUTC().toISO()) // converted using Luxon
// Or use UTC instead of Local
+ p(`~timeType~'${timeType}~tz~'Local~editorString~'`)
+ s(expression)
+ p('~isLiveTail~false~queryId~\'')
+ s(queryDefinitionId)
+ p("~source~(~'") + s(sourceGroup) + p(')')
+ p(')');
return `https://${region}.console.aws.amazon.com/cloudwatch/home?region=${region}#logsV2:logs-insights${escape(`?queryDetail=${queryDetail}`).replace(/%/gi, '$')}`;
}
Of course reverse operation can be performed as well.
That's all folks. Have fun, take care and try to avoid doing such a weird stuff yourselves. :)
I had to do a similar thing to generate a back link to the logs for a lambda and did the following hackish thing to create the link:
const link = `https://${process.env.AWS_REGION}.console.aws.amazon.com/cloudwatch/home?region=${process.env.AWS_REGION}#logsV2:log-groups/log-group/${process.env.AWS_LAMBDA_LOG_GROUP_NAME.replace(/\//g, '$252F')}/log-events/${process.env.AWS_LAMBDA_LOG_STREAM_NAME.replace('$', '$2524').replace('[', '$255B').replace(']', '$255D').replace(/\//g, '$252F')}`
A colleague of mine figured out that the encoding is nothing special. It is the standard URI percent encoding but applied twice (2x). In javascript you can use the encodeURIComponent function to test this out:
let inp = 'https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#logsV2:log-groups/log-group/'
console.log(encodeURIComponent(inp))
console.log(encodeURIComponent(encodeURIComponent(inp)))
This piece of javascript produces the expected output on the second encoding stage:
https%3A%2F%2Fconsole.aws.amazon.com%2Fcloudwatch%2Fhome%3Fregion%3Dus-east-1%23logsV2%3Alog-groups%2Flog-group%2F
https%253A%252F%252Fconsole.aws.amazon.com%252Fcloudwatch%252Fhome%253Fregion%253Dus-east-1%2523logsV2%253Alog-groups%252Flog-group%252F
Caution
At least some bits use the double encoding, not the whole link though. Otherwise all special characters would occupy 4 characters after double encoding, but some still occupy only 2 characters. Hope this helps anyway ;)
My complete Javascript solution based on #isaias-b answer, which also adds a timestamp filter on the logs:
const logBaseUrl = 'https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#logsV2:log-groups/log-group';
const encode = text => encodeURIComponent(text).replace(/%/g, '$');
const awsEncode = text => encodeURIComponent(encodeURIComponent(text)).replace(/%/g, '$');
const encodeTimestamp = timestamp => encode('?start=') + awsEncode(new Date(timestamp).toJSON());
const awsLambdaLogBaseUrl = `${logBaseUrl}/${awsEncode('/aws/lambda/')}`;
const logStreamUrl = (logGroup, logStream, timestamp) =>
`${awsLambdaLogBaseUrl}${logGroup}/log-events/${awsEncode(logStream)}${timestamp ? encodeTimestamp(timestamp) : ''}`;
I have created a bit of Ruby code that seems to satisfy the CloudWatch URL parser. I'm not sure why you have to double escape some things and then replace % with $ in others. I'm guessing there is some reason behind it but I couldn't figure out a nice way to do it, so I'm just brute forcing it. If you have something better, or know why they do this, please add a comment.
NOTE: The filter I tested with is kinda basic and I'm not sure what might need to change if you get really fancy with it.
# Basic URL that is the same across all requests
url = 'https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#logsV2:log-groups/log-group/'
# CloudWatch log group
log_group = '/aws/my/log/group'
# Either specify the instance you want to search or leave it out to search all instances
instance = '/log-events/i-xxxxxxxxxxxx'
OR
instance = '/log-events'
# The filter to apply.
filter = '[incoming_ip, user_name, user_ip , timestamp, request, status_code = 5*, bytes, url, user_agent]'
# Start time. There might be an End time as well but my queries haven't used
# that yet so I'm not sure how it's formatted. It should be pretty similar
# though.
hours = 48
start = "&start=-#{hours*60*60*1000}"
# This will get you the final URL
final = url + CGI.escape(CGI.escape(log_group)) + instance + '$3FfilterPattern$3D' + CGI.escape(CGI.escape(filter)).gsub('%','$') + CGI.escape(start).gsub('%','$')
A bit late but here is a python implementation
def get_cloud_watch_search_url(search, log_group, log_stream, region=None,):
"""Return a properly formatted url string for search cloud watch logs
search = "{$.message: "You are amazing"}
log_group = Is the group of message you want to search
log_stream = The stream of logs to search
"""
url = f'https://{region}.console.aws.amazon.com/cloudwatch/home?region={region}'
def aws_encode(value):
"""The heart of this is that AWS likes to quote things twice with some substitution"""
value = urllib.parse.quote_plus(value)
value = re.sub(r"\+", " ", value)
return re.sub(r"%", "$", urllib.parse.quote_plus(value))
bookmark = '#logsV2:log-groups'
bookmark += '/log-group/' + aws_encode(log_group)
bookmark += "/log-events/" + log_stream
bookmark += re.sub(r"%", "$", urllib.parse.quote("?filterPattern="))
bookmark += aws_encode(search)
return url + bookmark
This then allows you to quickly verify it.
>>> real = 'https://us-west-2.console.aws.amazon.com/cloudwatch/home?region=us-west-2#logsV2:log-groups/log-group/$252Fapp$252Fdjango/log-events/production$3FfilterPattern$3D$257B$2524.msg$253D$2522$2525s$2525s+messages+to+$2525s+pk$253D$2525d...$2522$257D'
>>> constructed = get_cloud_watch_search_url(None, search='{$.msg="%s%s messages to %s pk=%d..."}', log_group='/app/django', log_stream='production', region='us-west-2')
>>> real == constructed
True
I encountered this problem recently when I wanted to generate cloudwatch insights URL. Typescript version below:
export function getInsightsUrl(
start: Date,
end: Date,
query: string,
sourceGroup: string,
region = "us-east-1"
) {
const p = (m: string) => escape(m);
// encodes inner values
const s = (m: string) => escape(m).replace(/\%/gi, "*");
const queryDetail =
p(`~(end~'`) +
s(end.toISOString()) +
p(`~start~'`) +
s(start.toISOString()) +
p(`~timeType~'ABSOLUTE~tz~'UTC~editorString~'`) +
s(query) +
p(`~isLiveTail~false~queryId~'`) +
s(v4()) +
p(`~source~(~'`) +
s(sourceGroup) +
p(`))`);
return (
`https://console.aws.amazon.com/cloudwatch/home?region=${region}#logsV2:logs-insights` +
escape("?queryDetail=" + queryDetail).replace(/\%/gi, "$")
);
}
Github GIST
A Python solution based on #Pål Brattberg's answer:
cloudwatch_log_template = "https://{AWS_REGION}.console.aws.amazon.com/cloudwatch/home?region={AWS_REGION}#logsV2:log-groups/log-group/{LOG_GROUP_NAME}/log-events/{LOG_STREAM_NAME}"
log_url = cloudwatch_log_template.format(
AWS_REGION=AWS_REGION, LOG_GROUP_NAME=CLOUDWATCH_LOG_GROUP, LOG_STREAM_NAME=LOG_STREAM_NAME
)
Make sure to substitute illegal characters first (see OP) if you used any.
I encountered this problem recently when I wanted to generate cloudwatch insights URL. PHP version below:
<?php
function getInsightsUrl($region = 'ap-northeast-1') {
// https://stackoverflow.com/questions/67734825/why-is-laravels-carbon-toisostring-different-from-javascripts-toisostring
$start = now()->subMinutes(2)->format('Y-m-d\TH:i:s.v\Z');
$end = now()->addMinutes(2)->format('Y-m-d\TH:i:s.v\Z');
$filter = 'INFO';
$logStream = 'xxx_backend_web';
$sourceGroup = '/ecs/xxx_backend_prod';
// $sourceGroup = '/aws/ecs/xxx_backend~\'/ecs/xxx_backend_dev'; // multiple source group
$query =
"fields #timestamp, #message \n" .
"| sort #timestamp desc\n" .
"| filter #logStream like '$logStream'\n" .
"| filter #message like '$filter'\n" .
"| limit 20";
$queryDetail = urlencode(
("~(end~'") .
($end) .
("~start~'") .
($start) .
("~timeType~'ABSOLUTE~tz~'Local~editorString~'") .
($query) .
("~isLiveTail~false~queryId~'") .
("~source~(~'") .
($sourceGroup) .
("))")
);
$queryDetail = preg_replace('/\%/', '$', urlencode("?queryDetail=" . $queryDetail));
return
"https://console.aws.amazon.com/cloudwatch/home?region=${region}#logsV2:logs-insights"
. $queryDetail;
}
A coworker came up with the following JavaScript solution.
import JSURL from 'jsurl';
const QUERY = {
end: 0,
start: -3600,
timeType: 'RELATIVE',
unit: 'seconds',
editorString: "fields #timestamp, #message, #logStream, #log\n| sort #timestamp desc\n| limit 200\n| stats count() by bin(30s)",
source: ['/aws/lambda/simpleFn'],
};
function toLogsUrl(query) {
return `#logsV2:logs-insights?queryDetail=${JSURL.stringify(query)}`;
}
toLogsUrl(QUERY);
// #logsV2:logs-insights?queryDetail=~(end~0~start~-3600~timeType~'RELATIVE~unit~'seconds~editorString~'fields*20*40timestamp*2c*20*40message*2c*20*40logStream*2c*20*40log*0a*7c*20sort*20*40timestamp*20desc*0a*7c*20limit*20200*0a*7c*20stats*20count*28*29*20by*20bin*2830s*29~source~(~'*2faws*2flambda*2fsimpleFn))
I HAVE to elevate #WayneB's answer above bc it just works. No encoding required - just follow his template. I just confirmed it works for me. Here's what he said in one of the comments above:
"Apparently there is an easier link which does the encoding/replacement for you: https://console.aws.amazon.com/cloudwatch/home?region=${process.env.AWS_REGION}#logEventViewer:group=${logGroup};stream=${logStream}"
Thanks for this answer Wayne - just wish I saw it sooner!
Since Python contributions relate to log-groups, and not to log-insights, this is my contribution. I guess that I could have done better with the inner functions though, but it is a good starting point:
from datetime import datetime, timedelta
import re
from urllib.parse import quote
def get_aws_cloudwatch_log_insights(query_parameters, aws_region):
def quote_string(input_str):
return f"""{quote(input_str, safe="~()'*").replace('%', '*')}"""
def quote_list(input_list):
quoted_list = ""
for item in input_list:
if isinstance(item, str):
item = f"'{item}"
quoted_list += f"~{item}"
return f"({quoted_list})"
params = []
for key, value in query_parameters.items():
if key == "editorString":
value = "'" + quote(value)
value = value.replace('%', '*')
elif isinstance(value, str):
value = "'" + value
if isinstance(value, bool):
value = str(value).lower()
elif isinstance(value, list):
value = quote_list(value)
params += [key, str(value)]
object_string = quote_string("~(" + "~".join(params) + ")")
scaped_object = quote(object_string, safe="*").replace("~", "%7E")
with_query_detail = "?queryDetail=" + scaped_object
result = quote(with_query_detail, safe="*").replace("%", "$")
final_url = f"https://{aws_region}.console.aws.amazon.com/cloudwatch/home?region={aws_region}#logsV2:logs-insights{result}"
return final_url
Example:
aws_region = "eu-west-1"
query = """fields #timestamp, #message
| filter #message not like 'example'
| sort #timestamp asc
| limit 100"""
log_groups = ["/application/sample1", "/application/sample2"]
query_parameters = {
"end": datetime.utcnow().isoformat(timespec='milliseconds') + "Z",
"start": (datetime.utcnow() - timedelta(days=2)).isoformat(timespec='milliseconds') + "Z",
"timeType": "ABSOLUTE",
"unit": "seconds",
"editorString": query,
"isLiveTrail": False,
"source": log_groups,
}
print(get_aws_cloudwatch_log_insights(query_parameters, aws_region))
Yet another Python solution:
from urllib.parse import quote
def aws_quote(s):
return quote(quote(s, safe="")).replace("%", "$")
def aws_cloudwatch_url(region, log_group, log_stream):
return "/".join([
f"https://{region}.console.aws.amazon.com/cloudwatch/home?region={region}#logsV2:log-groups",
"log-group",
aws_quote(log_group),
"log-events",
aws_quote(log_stream),
])
aws_cloudwatch_url("ap-southeast-2", "/var/log/syslog", "process/pid=1")
https://ap-southeast-2.console.aws.amazon.com/cloudwatch/home?region=ap-southeast-2#logsV2:log-groups/log-group/$252Fvar$252Flog$252Fsyslog/log-events/process$252Fpid$253D1

LibreOffice Macro mac find and replace spaces by underscore bug

I want to create a shortcut in libreoffice to replace spaces by underscore.
I recorded a macro
I performed a simple find & replace.
But everytime I try to run the macro libreoffice quit ;(
this is the code
REM ***** BASIC *****
sub replacespaces
rem ----------------------------------------------------------------------
rem define variables
dim document as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
rem ----------------------------------------------------------------------
dim args1(17) as new com.sun.star.beans.PropertyValue
args1(0).Name = "SearchItem.StyleFamily"
args1(0).Value = 2
args1(1).Name = "SearchItem.CellType"
args1(1).Value = 0
args1(2).Name = "SearchItem.RowDirection"
args1(2).Value = true
args1(3).Name = "SearchItem.AllTables"
args1(3).Value = false
args1(4).Name = "SearchItem.Backward"
args1(4).Value = false
args1(5).Name = "SearchItem.Pattern"
args1(5).Value = false
args1(6).Name = "SearchItem.Content"
args1(6).Value = false
args1(7).Name = "SearchItem.AsianOptions"
args1(7).Value = false
args1(8).Name = "SearchItem.AlgorithmType"
args1(8).Value = 1
args1(9).Name = "SearchItem.SearchFlags"
args1(9).Value = 71680
args1(10).Name = "SearchItem.SearchString"
args1(10).Value = " "
args1(11).Name = "SearchItem.ReplaceString"
args1(11).Value = "_"
args1(12).Name = "SearchItem.Locale"
args1(12).Value = 255
args1(13).Name = "SearchItem.ChangedChars"
args1(13).Value = 2
args1(14).Name = "SearchItem.DeletedChars"
args1(14).Value = 2
args1(15).Name = "SearchItem.InsertedChars"
args1(15).Value = 2
args1(16).Name = "SearchItem.TransliterateFlags"
args1(16).Value = 1280
args1(17).Name = "SearchItem.Command"
args1(17).Value = 3
dispatcher.executeDispatch(document, ".uno:ExecuteSearch", "", 0, args1())
rem ----------------------------------------------------------------------
dispatcher.executeDispatch(document, ".uno:SearchResultsDialog", "", 0, Array())
end sub
Can someone tell me what's wrong ?
The macro recorder of openoffice and libreoffice is not really so much helpful as the one of Microsoft Office. I would suggest not to use it. Instead recording a macro, use a tool like XRAY ( https://wiki.documentfoundation.org/Macros) for examining the objects you have found using the methods of the API. At first examine thisComponent. Doing so, with Calc, you will find a model which has multiple models of sheets which each implements an interface XReplaceable (http://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1util_1_1XReplaceable.html).
Example:
Sub findAndReplace()
oModel = thisComponent ' at first examine thisComponent
' xray oModel
oSpreadSheet = oModel.getCurrentController().getActiveSheet()
' oSpreadSheet = oModel.getSheets().getByIndex(0)
' xray oSpreadSheet
xReplaceDescr = oSpreadSheet.createReplaceDescriptor()
' xray xReplaceDescr
xReplaceDescr.SearchString = " "
xReplaceDescr.ReplaceString = "_"
lFound = oSpreadSheet.replaceAll(xReplaceDescr)
' xray lFound
MsgBox lFound & " replacements done."
End Sub

how to geocode lat and long coordinates from an address search in php

I am trying to enter new locations into a database and would like the lat and long coordinates entered correctly for mapping purposes.I have researched Googles help forum on the subject and came up with this code.
Currently, I have a table for back up that has a generic lat and long code if the address is not successful through my google maps call. That is working, but I would like the exact coordinates if possible and the google maps call does nothing. Here is my code. (I have taken out my google aps key and substituted "my key"
if($facility_enter){
//GEOCODE
define("MAPS_HOST", "maps.google.com");
define("KEY", "my key");
// Do API find, returning address and id
// Initialize delay in geocode speed
$delay = 0;
$base_url = "http://" . MAPS_HOST . "/maps/geo?output=xml" . "&key=" . KEY;
//Get Address
$full_address = $_POST['fac_add'] . ' ' . $_POST['fac_city'] . ' ' .
$_POST['fac_state'] . ' ' .
$_POST['fac_zip'];
$prepAddr = str_replace(' ','+',$full_address);
$request_url = $base_url . "&q=" . urlencode($prepAddr);
$xml = simplexml_load_file($request_url);
$status = $xml->Response->Status->code;
//if successful
if (strcmp($status, "200") == 0) {
$coordinates = $xml->Response->Placemark->Point->coordinates;
$coordinatesSplit = split(",", $coordinates);
$lat = $coordinatesSplit[1];
$lng = $coordinatesSplit[0];
}
//otherwise just pull the generic zip code coords from the database
else{
$zip_sql = 'SELECT lat,lng FROM blahblah.zips WHERE zip = "' . $_POST['fac_zip'] .
'"';
$zip_res = mysql_query($zip_sql,$my_db);
$coords = mysql_fetch_array($zip_res);
$lat = $coords['lat'];
$lng = $coords['lng'];
}

django make log that works for all models

I am trying to make my own log that makes a string of changed data between object (my old object and my new object) However i keep getting back empty string,
My code:
def log_fields(old_obj, new_obj):
fields = new_obj.__class__._meta.fields
changed_fields = ""
old_data = ""
new_data = ""
# get all changed data
for field in fields:
old_field_data = old_obj.__getattribute__(field.name)
new_field_data = new_obj.__getattribute__(field.name)
if old_field_data != new_field_data:
count =+ 1
# convert changed data to strings
# number + space + data + 5 spaces for next string
changed_fields.join(str(count)).join(" ").join(str(field)).join(" ")
old_data.join(str(count)).join(" ").join(str(old_field_data)).join(" ")
new_data.join(str(count)).join(" ").join(str(new_field_data)).join(" ")
print changed_fields
print old_data
print new_data
I got a feeling something with the string .join combination something is going wrong, cause trying this manually in shell seems to work up to the comparison. Not sure tho hos i should change the string
changed_fields = changed_fields + str(count) + "." + str(field.name) + " "
old_data = old_data + str(count) + "." + str(old_field_data) + " "
new_data = new_data + str(count) + "." + str(new_field_data) + " "
Seems to do the job, so for now, ill keep it at this

Shortcut to change a line of words to a vertical list in Sublime Text 2

Is it possible to make this title on line 1 a list of items from each word or symbol seperated by a space with a keyboard shortcut. So that I can select the title and then hit a shortcut and it will make the title a list of items like below:
Tried saving the Key Binding file.
Nothing built in, but you can do it with a plugin.
import sublime
import sublime_plugin
import re
class SplitLineCommand(sublime_plugin.TextCommand):
def run(self, edit, split_pattern=" "):
view = self.view
cursors = view.sel()
if len(cursors) == 1:
cursor = cursors[0]
begin_offset = 0
end_offset = 0
if cursor.empty():
region = view.line(cursor)
content = view.substr(region)
new_content = re.sub(split_pattern, "\n", content)
view.replace(edit, region, new_content)
else:
region = cursor
content = view.substr(region)
new_content = ""
if view.line(region).begin() != region.begin():
new_content = "\n"
begin_offset = 1
new_content += re.sub(split_pattern, "\n", content)
if view.line(region).end() != region.end():
new_content += "\n"
end_offset = - 1
view.replace(edit, region, new_content)
cursors.clear()
cursors.add(sublime.Region(region.begin() + begin_offset, region.begin() + len(new_content) + end_offset))
view.run_command("split_selection_into_lines")
You can then add the following in your key binding file.
[
{ "keys": ["f8"], "command": "split_line", "args": {"split_pattern": " "}}
]
Of course changing the key to something that you want. You don't actually need the args argument if you are just using a space. It defaults to that. I just included it for completeness.
Edit:
I've updated the plugin so it now handles selections, though it does not handle multiple cursors at this point.
Edit 2
If it is not working, try opening the console and entering view.run_command("split_line"). This will run the command in whatever view you were in prior to switching to the console. This way you know if the command actually works. If it doesn't then there is a problem with the plugin. If it does, then there is a problem with the key binding.
I adapted the above code for my own use, so that it now respects whitespace. But I hard-coded tabs instead of spaces, so if you use spaces you might have to change it further. It also now assumes you have no text selected and instead have the cursor in the middle of the line to be changed to vertical spacing. I left intro/outro as arguments so you can also use it for [] or (), although maybe some more escaping is needed in that case for the regex.
Before:
fields = { 'Team1', 'Team2', 'Player1', 'Player2', 'Tab=Round', 'DateTime_UTC=DateTime', 'HasTime=TimeEntered', 'OverviewPage=Tournament', 'ShownName', 'Winner', 'Stream' },
After:
fields = {
'Team1',
'Team2',
'Player1',
'Player2',
'Tab=Round',
'DateTime_UTC=DateTime',
'HasTime=TimeEntered',
'OverviewPage=Tournament',
'ShownName',
'Winner',
'Stream',
},
import sublime
import sublime_plugin
import re
class SplitLineCommand(sublime_plugin.TextCommand):
def run(self, edit, sep=",", repl= "\n", intro="{", outro="}"):
view = self.view
find = re.escape(sep + ' ') + '*(?! *$| *\n)'
intro_repl = intro + repl
intro = intro + ' *'
outro_repl_start = sep + repl
outro_repl_end = outro
outro = ',? *' + outro
repl = sep + repl
cursors = view.sel()
if len(cursors) == 1:
cursor = cursors[0]
begin_offset = 0
end_offset = 0
if cursor.empty():
region = view.line(cursor)
content = view.substr(region)
line_str = view.substr(view.line(view.sel()[0]))
tabs = len(line_str) - len(line_str.lstrip())
intro_repl = intro_repl + '\t' * (tabs + 1)
repl = repl + '\t' * (tabs + 1)
outro_repl = outro_repl_start + ('\t' * tabs) + outro_repl_end
content = re.sub(outro, outro_repl, content)
content = re.sub(find, repl, content)
content = re.sub(intro, intro_repl, content)
view.replace(edit, region, content)
cursors.clear()
cursors.add(sublime.Region(region.begin() + begin_offset, region.begin() + len(content) + end_offset))
view.run_command("split_selection_into_lines")