Posts: 1,049
Threads: 249
Joined: Jul 2022
10-13-2022, 10:15 AM
(This post was last modified: 10-13-2022, 10:27 AM by Davider.)
Hi,
The following C# code, in linqpad, can be executed successfully, It supports the following picture formats,This is convenient
But when I copy the code into the LA, there will be a hint in the picture below, where the red box part is the wrong hint
If I click the Yes button, I need to manually delete these erroneous items
I suggest that LA can support the format of the picture below, do not pop up the prompt ( Don't put using code in top comments)
After I made the modification, I executed the code and still reported an error, maybe that using the main method directly is not supported
It seems that copying code to LA from Linqpad is not very convenient and requires a lot of modifications
using Spire.Doc;
using Spire.Doc.Documents;
using Spire.Doc.Fields;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
static void Main(string[] args)
{
Environment.CurrentDirectory = @"C:\Users\Administrator\Desktop";
Document doc = new Document();
doc.LoadFromFile(@"Test2b.docx");
foreach (Section section in doc.Sections)
{
foreach (Paragraph paragraph in section.Body.Paragraphs)
{
if (paragraph.StyleName != "Heading1")
{
HashSet<float> fontSize = new HashSet<float>();
HashSet<Color> fontColor = new HashSet<Color>();
foreach (DocumentObject paraChildObject in paragraph.ChildObjects)
{
if (paraChildObject.DocumentObjectType == DocumentObjectType.TextRange)
{
TextRange textRange = paraChildObject as TextRange;
Font font = textRange.CharacterFormat.Font;
fontSize.Add(font.Size);
Color color = textRange.CharacterFormat.TextColor;
fontColor.Add(color);
if (font.Name == "kaiti")
{
textRange.CharacterFormat.Font = new Font("liti", font.Size);
}
}
}
if (fontSize.Count > 1)
{
setA(paragraph);
}
}
}
}
doc.SaveToFile(@"result.docx", FileFormat.Docx);
}
public static void setA(Paragraph para)
{
para.Format.BeforeSpacing = 8f;
para.Format.AfterSpacing = 16f;
para.Format.LineSpacing = 16f;
para.Format.LineSpacingRule = LineSpacingRule.Exactly;
foreach (DocumentObject paraChildObject in para.ChildObjects)
{
if (paraChildObject.DocumentObjectType == DocumentObjectType.TextRange)
{
TextRange textRange = paraChildObject as TextRange;
if (Regex.IsMatch(textRange.Text, "^([A-Za-z]){1}[^.]*."))
{
textRange.CharacterFormat.Font = new Font("Consolas", 14);
}
if (Regex.IsMatch(textRange.Text, "^[\u4e00-\u9fbb]+"))
{
textRange.CharacterFormat.Font = new Font("宋体", 14);
}
}
}
}
Posts: 12,095
Threads: 142
Joined: Dec 2002
LA uses standard C#. It can be either class with Main, or top-level statements without Main.
In this case either:
1. Put both functions into a class.
class Program {
put code here
}
2. Or convert the code to valid top-level statements: move Main code out of Main (and delete Main), and delete the 'public' keyword (then the function will be a local function).
----------
About 'Add missing using directives': LA finds classes with same name in multiple namespaces, and cannot know which are correct. Either delete wrong usings, or click No and then add good usings.
Posts: 1,049
Threads: 249
Joined: Jul 2022
10-13-2022, 11:17 AM
(This post was last modified: 10-13-2022, 11:18 AM by Davider.)
Thank you for your help
Changing code 1 to code 2 is more in line with everyone's operating habits
________________________________________________code 1
/*/ role exeProgram; outputPath %folders.Workspace%\exe\Script1; r %dll%\spire\Spire.Doc.dll; /*/ //.
using Spire.Doc;
using Spire.Doc.Documents;
using Spire.Doc.Fields;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
script.setup(trayIcon: true, sleepExit: true);
//..
static void Main(string[] args)
________________________________________________code 2
/*/ role exeProgram; outputPath %folders.Workspace%\exe\Script1; r %dll%\spire\Spire.Doc.dll; /*/ //.
script.setup(trayIcon: true, sleepExit: true);
//..
using Spire.Doc;
using Spire.Doc.Documents;
using Spire.Doc.Fields;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
static void Main(string[] args)
Posts: 12,095
Threads: 142
Joined: Dec 2002
script.setup before usings is not possible, but you can prevent LA putting usings into //. //...
In script template (in Options) remove //. //... Can remove everything if don't need script.setup (it is optional).
Actually script.setup can be moved to a module initializer function in global.cs. Not tested. But then it will be executed in all scripts. Probably not a good idea.
Maybe LA should have option "put usings into /. //..".
Posts: 1,049
Threads: 249
Joined: Jul 2022
10-13-2022, 01:18 PM
(This post was last modified: 10-13-2022, 01:26 PM by Davider.)
code1 can execute successfully
code2 still has the following error message
<open "<0x100000043>|16|7">Script1.cs(16,7): error CS0260: Missing partial modifier on declaration of type 'Program'; another partial declaration of this type exists
<open "<0x100000043>|17|14">Script1.cs(17,14): warning CS7022: The entry point of the program is global code; ignoring 'Program.Main(string[])' entry point.
code1
/*/ role exeProgram; outputPath %folders.Workspace%\exe\Script1; r %dll%\spire\Spire.Doc.dll; r %dll%\spire\Spire.PDF.dll; /*/
using Spire.Doc;
using Spire.Doc.Documents;
using Spire.Doc.Fields;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
class Program {
static void Main(string[] args) {
Environment.CurrentDirectory = @"C:\Users\Administrator\Desktop";
Document doc = new Document();
doc.LoadFromFile(@"Test2b.docx");
foreach (Section section in doc.Sections) {
foreach (Paragraph paragraph in section.Body.Paragraphs) {
if (paragraph.StyleName != "Heading1") {
HashSet<float> fontSize = new HashSet<float>();
HashSet<Color> fontColor = new HashSet<Color>();
foreach (DocumentObject paraChildObject in paragraph.ChildObjects) {
if (paraChildObject.DocumentObjectType == DocumentObjectType.TextRange) {
TextRange textRange = paraChildObject as TextRange;
Font font = textRange.CharacterFormat.Font;
fontSize.Add(font.Size);
Color color = textRange.CharacterFormat.TextColor;
fontColor.Add(color);
if (font.Name == "kaiti") {
textRange.CharacterFormat.Font = new Font("liti", font.Size);
}
}
}
if (fontSize.Count > 1) {
setA(paragraph);
}
}
}
}
doc.SaveToFile(@"result.docx", FileFormat.Docx);
}
public static void setA(Paragraph para) {
para.Format.BeforeSpacing = 8f;
para.Format.AfterSpacing = 16f;
para.Format.LineSpacing = 16f;
para.Format.LineSpacingRule = LineSpacingRule.Exactly;
foreach (DocumentObject paraChildObject in para.ChildObjects) {
if (paraChildObject.DocumentObjectType == DocumentObjectType.TextRange) {
TextRange textRange = paraChildObject as TextRange;
if (Regex.IsMatch(textRange.Text, "^([A-Za-z]){1}[^.]*.")) {
textRange.CharacterFormat.Font = new Font("Consolas", 14);
}
if (Regex.IsMatch(textRange.Text, "^[\u4e00-\u9fbb]+")) {
textRange.CharacterFormat.Font = new Font("宋体", 14);
}
}
}
}
}
code2
/*/ role exeProgram; outputPath %folders.Workspace%\exe\Script1; r %dll%\spire\Spire.Doc.dll; r %dll%\spire\Spire.PDF.dll;/*/
using Spire.Doc;
using Spire.Doc.Documents;
using Spire.Doc.Fields;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
script.setup(trayIcon: true, sleepExit: true);
//..
class Program {
static void Main(string[] args) {
Environment.CurrentDirectory = @"C:\Users\Administrator\Desktop";
Document doc = new Document();
doc.LoadFromFile(@"Test2b.docx");
foreach (Section section in doc.Sections) {
foreach (Paragraph paragraph in section.Body.Paragraphs) {
if (paragraph.StyleName != "Heading1") {
HashSet<float> fontSize = new HashSet<float>();
HashSet<Color> fontColor = new HashSet<Color>();
foreach (DocumentObject paraChildObject in paragraph.ChildObjects) {
if (paraChildObject.DocumentObjectType == DocumentObjectType.TextRange) {
TextRange textRange = paraChildObject as TextRange;
Font font = textRange.CharacterFormat.Font;
fontSize.Add(font.Size);
Color color = textRange.CharacterFormat.TextColor;
fontColor.Add(color);
if (font.Name == "kaiti") {
textRange.CharacterFormat.Font = new Font("liti", font.Size);
}
}
}
if (fontSize.Count > 1) {
setA(paragraph);
}
}
}
}
doc.SaveToFile(@"result.docx", FileFormat.Docx);
}
public static void setA(Paragraph para) {
para.Format.BeforeSpacing = 8f;
para.Format.AfterSpacing = 16f;
para.Format.LineSpacing = 16f;
para.Format.LineSpacingRule = LineSpacingRule.Exactly;
foreach (DocumentObject paraChildObject in para.ChildObjects) {
if (paraChildObject.DocumentObjectType == DocumentObjectType.TextRange) {
TextRange textRange = paraChildObject as TextRange;
if (Regex.IsMatch(textRange.Text, "^([A-Za-z]){1}[^.]*.")) {
textRange.CharacterFormat.Font = new Font("Consolas", 14);
}
if (Regex.IsMatch(textRange.Text, "^[\u4e00-\u9fbb]+")) {
textRange.CharacterFormat.Font = new Font("宋体", 14);
}
}
}
}
}
Linqpad has a big problem, it can't generate exe files, which happens to be the advantage of LA
But after the linqpad code is copied to the LA, there are still many modifications to be made, which is not very convenient
Posts: 12,095
Threads: 142
Joined: Dec 2002
10-13-2022, 02:05 PM
(This post was last modified: 10-13-2022, 02:07 PM by Gintaras.)
script.setup(trayIcon: true, sleepExit: true);
is top-level-statements. The C# compiler converts it to classic C# code like
class Program {
static void Main() {
script.setup(trayIcon: true, sleepExit: true);
}}
Then the compilation contains 2 class Program.
Either remove
class Program {
static void Main(string[] args) {
and } and }
or move
script.setup(trayIcon: true, sleepExit: true);
to Main.
Posts: 1,049
Threads: 249
Joined: Jul 2022
Posts: 12,095
Threads: 142
Joined: Dec 2002
If want to use script.setup but not in script code, probably the best way is this:
1. Create a class file like this:
// class "script_setup_tray_icon.cs"
class _ModuleInit_ {
[ModuleInitializer]
public static void Function1() {
script.setup(trayIcon: true, sleepExit: true);
}
}
2. Add the class file in scripts where you want to use this script.setup, like this:
// script ""
/*/ c \script_setup_tray_icon.cs; /*/
dialog.showYesNo("Do you see my tray icon?");
You can create several such class files, each with different script.setup arguments or completely different code. Then some scripts can use class file 1, some scripts class file 2...
And edit the template in Options. Let it be empty or contain just the /*/ ... /*/.
Note that module initializers run before other code, therefore something may not work. But script.setup should work. Not tested much.
Posts: 1,049
Threads: 249
Joined: Jul 2022
10-14-2022, 12:36 AM
(This post was last modified: 10-14-2022, 01:03 AM by Davider.)
Thanks again,
The above operation Can implemented automatically? e.g:
1.If the code in the clipboard, which contains using code, is no longer prompted for the following window (which is redundant)
2.If the role is exeProgram, Check if the code contains class Program { }, If not, it is added automatically, and some other considerations above ...
These checks are also done when roles change(form miniProgram 2 exeProgram)
3.Put the drop-down list of role selections next to the Compile button to make it easier
4.If the Au.dll class library is not referenced in the code, the generated exe file will not contain the files ( Au.dll , AuCpp.dll , etc )
The above automation operations for linqpad users, It's a gospel, very libre automate
generate exe , is the most mentioned recommendation by linqpad users, but it is still not implemented
https://linqpad.uservoice.com/forums/183...uggestions
Posts: 12,095
Threads: 142
Joined: Dec 2002
10-14-2022, 05:08 AM
(This post was last modified: 10-14-2022, 04:49 PM by Gintaras.)
1. It happens when code with using directives is pasted below script.setup. If you import many such codes, consider to remove script.setup from your script template in Options (maybe temporarily). Let it be empty.
2. exeProgram and class Program are unrelated. Usually don't need class Program. See also menu Edit -> Document -> Add class Program.
3. No.
4. The compiled program uses these dlls even if script code does not use them directly.
Posts: 1,049
Threads: 249
Joined: Jul 2022
#4
A bit hard to understand, can't generate a separate exe?
Using the following tool, I can generate separate, very small, exe files for .linq
https://github.com/atifaziz/LinqPadless
Posts: 12,095
Threads: 142
Joined: Dec 2002
10-17-2022, 05:52 AM
(This post was last modified: 10-17-2022, 05:56 AM by Gintaras.)
Can't create single-file .exe.
Even without Au.dll would create ScriptName.exe + ScriptName.dll. With old .NET 4.x could be single .exe file, but for .NET 6 need .exe and .dll.
Au.dll performs many auxiliary tasks, for example prints exception info when failed, allows to terminate more softly (remove tray icon etc), sets script class properties, workarounds for .NET/OS bugs, etc.
Posts: 1,049
Threads: 249
Joined: Jul 2022
|