Здравствуйте, gandjustas, Вы писали:
V>>Тебе коллега правильно сказал — там используется функциональность браузера (АПИ DOM), а не языка JS.
V>>От JS там только динамическое выполнение кода в ячейках, но это умеют, наверно, вообще все динамические языки.
G>Накатай на любом удобном тебе языке. Уложись в 30 строк. Представь что у тебя в любом языке есть DOM API и уложись в 30 строк.
С таким форматированием? ))
Спасибо.
А если с другим форматированием в чуть большее кол-во строк на C#?
| Так пойдёт? |
| void MakeExcel()
{
dynamic document = webBrowser1.Document.DomDocument;
var localStorage = new Dictionary<string, string>();
dynamic table = document.querySelector("table");
for (var i = 0; i < 6; i++) {
dynamic row = table.insertRow(-1);
for (var j = 0; j < 6; j++) {
char letter = (char)('A' + j - 1);
row.insertCell(-1).innerHtml = i != 0 && j != 0
? "<input id='" + letter + i + "'/>"
: i == 0 ? letter.ToString() : i.ToString();
}
}
dynamic inputs = document.querySelectorAll("input");
var INPUTS = new List<HtmlElement>();
for (int i = 0, length = inputs.length; i < length; i++) {
dynamic input = inputs[i];
INPUTS.Add(webBrowser1.Document.GetElementById(input.id));
}
Func<string, object> getter = (id) => {
if (!localStorage.ContainsKey(id))
return "";
string value = localStorage[id];
if (value.FirstOrDefault() == '=')
return Eval(localStorage, value.Substring(1));
else {
float parsed;
return float.TryParse(value, out parsed) ? parsed : (object)value;
}
};
Action computeAll = () => {
foreach (var elm in INPUTS) {
try {
dynamic e = elm.DomElement;
e.value = getter(e.id);
} catch {}
};
};
foreach (var elm in INPUTS) {
elm.GotFocus += (obj, args) => {
dynamic e = ((HtmlElement)obj).DomElement;
string value;
if (localStorage.TryGetValue(e.id, out value))
e.value = value;
else
e.value = "";
};
elm.LostFocus += (obj, args) => {
dynamic e = ((HtmlElement)obj).DomElement;
localStorage[e.id] = e.value;
computeAll();
};
};
computeAll();
}
|
| |
Работает...
Основные ужимки и прыжки были в том, что для доступа к DOM нужно переводить в dynamic, но при этом не получается подписаться на события, т.е. делегат не принимается.
В одном коде пришлось совместить как dynamic, так и типизированный HtmlElement сугубо для подписки на события.
Основные лишние строки именно отсюда.
И да, пытался сначала сделать на VBS в браузере, но мой IE11 говорит, что больше не поддерживает VBS.
Так шта, конкретно JS тут не при чём, он уродлив в любом случае.
А DOM мощный, это да...
| За отдельную доплату будет Eval в C# |
| static string Eval(Dictionary<string, string> vars, string expression)
{
CSharpCodeProvider c = new CSharpCodeProvider();
ICodeCompiler icc = c.CreateCompiler();
CompilerParameters cp = new CompilerParameters();
cp.ReferencedAssemblies.Add("system.dll");
cp.ReferencedAssemblies.Add("system.xml.dll");
cp.ReferencedAssemblies.Add("system.data.dll");
cp.ReferencedAssemblies.Add("system.windows.forms.dll");
cp.ReferencedAssemblies.Add("system.drawing.dll");
cp.CompilerOptions = "/t:library";
cp.GenerateInMemory = true;
StringBuilder sb = new StringBuilder("");
sb.Append("using System;\n");
sb.Append("using System.Xml;\n");
sb.Append("using System.Data;\n");
sb.Append("using System.Data.SqlClient;\n");
sb.Append("using System.Windows.Forms;\n");
sb.Append("using System.Drawing;\n");
sb.Append("namespace CSCodeEvaler{ \n");
sb.Append("public class CSCodeEvaler{ \n");
sb.Append("public object EvalCode(){\n");
foreach (var pair in vars)
{
float value;
if (pair.Value == null || pair.Value.ToString() == "" ||
!float.TryParse(pair.Value.ToString(), out value))
sb.Append("float " + pair.Key + "=0;\n");
else
sb.Append("float " + pair.Key + "=" + pair.Value.ToString() + ";\n");
}
sb.Append("return " + expression + "; \n");
sb.Append("} \n");
sb.Append("} \n");
sb.Append("}\n");
CompilerResults cr = icc.CompileAssemblyFromSource(cp, sb.ToString());
if (cr.Errors.Count > 0)
return "#Error";
System.Reflection.Assembly a = cr.CompiledAssembly;
object o = a.CreateInstance("CSCodeEvaler.CSCodeEvaler");
Type t = o.GetType();
MethodInfo mi = t.GetMethod("EvalCode");
object s;
try
{
s = mi.Invoke(o, null);
}
catch
{
return "#Error";
}
return s.ToString();
}
|
| |
| И не забыть саму HTML страницу+стили из исходного примера |
| <!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<style>
input {
border: none;
width: 80px;
font-size: 14px;
padding: 2px;
}
input:hover {
background-color: #eee;
}
input:focus {
background-color: #ccf;
}
input:not(:focus) {
text-align: right;
}
table {
border-collapse: collapse;
}
td {
border: 1px solid #999;
padding: 0;
}
tr:first-child td,
td:first-child {
background-color: #ccc;
padding: 1px 3px;
font-weight: bold;
text-align: center;
}
footer {
font-size: 80%;
}
</style>
</head>
<body>
<p>Пример на C#</p>
<table></table>
</body>
</html>
|
| |
Там изначально о 30-ти строках не было и речи. ))
| Остальной код, подгружаем страницу в веб-контрол |
| private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
try
{
MakeExcel();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void Form1_Load(object sender, EventArgs e)
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "WindowsFormsApplication1.HTMLPage1.html";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
webBrowser1.DocumentText = reader.ReadToEnd();
}
}
|
| |